179

My android webviews are slow. This is on everything from phones to 3.0+ tablets with more than adequate specs

I know that webviews are supposed to be "limited" but I see web apps done with phone gap that must be using all sorts of CSS3 and JQuery sorcery, they run just fine and speedy

so I'm missing something, is there some kind of myWebview.SPEEDHACK(1) that I can use to speed things up?

also, sometimes the contents of my webview just simply don't load, instead of slowly loading, it just wont load. The asset I am testing with is stored locally, no errors.

Xcodian Solangi
  • 2,170
  • 4
  • 21
  • 49
CQM
  • 36,672
  • 69
  • 214
  • 357
  • 3
    Sounds like you need to post some code. – Jasoneer Sep 14 '11 at 20:17
  • 1
    possible duplicate of [Android WebView performance](http://stackoverflow.com/questions/4081250/android-webview-performance) – Ken White Feb 28 '14 at 01:09
  • 1
    @KenWhite except this question has more answers, this question has better and more comprehensive answers, this questions has twice as many views, both questions are over two years old, the version of android both of these questions applied to are obsolete... what exactly do you get out of flagging this? – CQM Feb 28 '14 at 04:58
  • @CQM: This question was flagged automatically by the system because of the duplicated answer of George Mays below. If his answer can be repeated verbatim as the answer to multiple posts, one of them is a duplicate of the other. The linked question was posted (and answered) first based on the post date. A duplicate is a duplicate, and the first post was the original (and the answers were earlier as well). I get nothing out of flagging this (and didn't in the first place). – Ken White Feb 28 '14 at 05:12
  • 1
    Also, don't use the click event in your apps, it adds a 300ms delay to respond on every click, to determine it's a click. Better use touchstart instead. I have made an clickhandler that uses two events and takes the first triggered event. I use 'touchstart click', so it also still works without a touchscreen. – Codebeat Apr 24 '15 at 08:00

10 Answers10

136

It depends on the web application being loaded. Try some of the approaches below:

Set higher render priority (deprecated from API 18+):

webview.getSettings().setRenderPriority(RenderPriority.HIGH);

Enable/disable hardware acceleration:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    // chromium, enable hardware acceleration
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
    // older android version, disable hardware acceleration
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Disable the cache (if you have problems with your content):

webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
peceps
  • 16,533
  • 10
  • 70
  • 77
  • 47
    I understand why setting the render priority to high would make it faster. but why turning off the cache? – Dimas Kotvan Jun 13 '13 at 18:58
  • 42
    The method setRederPriority is deprecated, see http://developer.android.com/reference/android/webkit/WebSettings.html – Victor Ionescu Sep 02 '13 at 08:21
  • 6
    Correct link for setRenderPriority is [here](http://developer.android.com/reference/android/webkit/WebSettings.html#setRenderPriority(android.webkit.WebSettings.RenderPriority)) – Christopher Perry Aug 28 '14 at 18:28
  • 1
    By setting these methods, the local html files are still taking time to load:( – Programmer Oct 03 '14 at 14:47
  • 2
    Where do I put this code in my App? Please help - I have the same problem on mission critical WebView – Levchik Aug 03 '15 at 15:03
  • 7
    why do you turn off the cache? – Hassy31 Mar 23 '16 at 05:35
  • 1
    These are some magical solutions without any explanation why they should make the WebView run faster. Cache is usually used for speeding things up. Therefore I downvoted this answer. – Miloš Černilovský Nov 15 '16 at 09:52
  • 2
    @MilošČernilovský Android has magical problems, so magical solutions to the rescue! – peceps Nov 16 '16 at 14:35
  • 2
    Turning off the cache because the questioner had trouble with his web content.. If you guys don't have a problem like that just leave the cache on – StefansArya Apr 06 '17 at 02:18
  • Enable Default Cache webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); – That's Enam Apr 12 '18 at 07:14
  • **I don't advice to do this**. You may get a crush on an unexpected device. See **here** [WebView in NestedScrollView gives Fatal signal 6 (SIGABRT) code -6 RenderThread(https://stackoverflow.com/q/40242623/1820553) **and** [Android Webview Crushes with GL error: GL_INVALID_VALUE](https://stackoverflow.com/q/58240883/1820553). **The solution is not using as shown in the first link.** – kelalaka Oct 08 '19 at 13:42
  • i agree with @kelalaka.i face the same issue on Samsung J3 - 5.1.1 – shadow Nov 05 '19 at 07:26
54

Adding this android:hardwareAccelerated="true" in the manifest was the only thing that significantly improved the performance for me

More info here: http://developer.android.com/guide/topics/manifest/application-element.html#hwaccel

Sergey Glotov
  • 19,479
  • 11
  • 78
  • 93
Sender
  • 651
  • 5
  • 4
  • 1
    This is only for API v11/Android 3.x and higher – Ludwo May 27 '13 at 08:46
  • 6
    Take care, there's an open bug related hardware accelerated WebViews, as stated in the question http://stackoverflow.com/q/17059899/225341 – Victor Ionescu Sep 02 '13 at 12:57
  • 1
    I have noticed that turning off hardware acceleration actually makes my app faster. With `android:hardwareAccelerated="true"` CSS 3D animations had long delays before they started, scrolling of DIVs inside other scrollable DIVs didn't work, and the app was more unstable. – Ernests Karlsons Jan 08 '14 at 10:06
  • 2
    the default value is "true" if you've set either minSdkVersion or targetSdkVersion to "14" or higher; – Vihaan Verma Aug 27 '16 at 13:41
37

The solution for us was the opposite. We disabled hardware acceleration on the WebView only (rather than on the entire app in the manifest) by using this code:

if (Build.VERSION.SDK_INT >= 11){
    webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

CSS3 animations are smoother now. We are using Android 4.0.

More info here: https://code.google.com/p/android/issues/detail?id=17352

Ena
  • 3,039
  • 30
  • 30
  • 4
    Unfortunately, this also prevents the html5 video component to work =/ – Ja͢ck Apr 30 '13 at 07:18
  • Didn't notice. We used a video view to play videos: fortunately we just needed a full screen video. As a workaround it's possible to have the webview transparent and a video view playing in the background, although I know it's not the same thing. – Ena Apr 30 '13 at 07:25
  • 1
    There's another problem with this fix. While touching the webview the graphic gets a bit distored. For example if you have an image with a cirle, you will notice little squares (pixels) on it instead of the smooth line. I can tell that with Android 4.3 fix is useless, it hasn't performance issues. – Ena Nov 11 '13 at 15:06
  • Sorry a bit new to android. Is this pasteable directly in the android manifest being that the manifest file is XML. Or is this supposed to be validated in the source code when loading the webview. Sorry for the noob question. – xMythicx Jul 28 '14 at 15:09
  • Add the lines to where you have made your WebView (in source code). – Ruraj Aug 29 '14 at 06:25
  • 1
    After adding, getting this error ```WebView not displayed because it is too large to fit into a software layer (or drawing cache), needs 11534400 bytes, only 8294400 available``` – Vadiraj Purohit Oct 06 '16 at 19:28
  • Wow, that was the solution for me too, thanks a lot! – shurrok Jan 12 '18 at 14:47
  • 6 yrs later ... this is still the one that worked for me – chitgoks Sep 15 '19 at 10:52
14

I think the following works best:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Android 19 has Chromium engine for WebView. I guess it works better with hardware acceleration.

Jared Burrows
  • 50,718
  • 22
  • 143
  • 180
Tedi
  • 149
  • 1
  • 2
10

I tried all the proposals to fix the render performance problem in my phonegap app. But nothing realy worked.

Finally, after a whole day of searching, I made it. I set within the tag (not the tag) of my AndroidManifest

<application android:hardwareAccelerated="false" ...

Now the app behaves in the same fast way as my webbrowser. Seems like, if hardware acceleration is not always the best feature...

The detailed problem I had: https://stackoverflow.com/a/24467920/3595386

Community
  • 1
  • 1
user3595386
  • 192
  • 1
  • 6
9

I was having this same issue and I had to work it out. I tried these solutions, but at the end the performance, at least for the scrolling didn't improve at all. So here the workaroud that I did perform and the explanation of why it did work for me.

If you had the chance to explore the drag events, just a little, by creating a "MiWebView" Class, overwriting the "onTouchEvent" method and at least printed the time in which every drag event occurs, you'll see that they are separated in time for (down to) 9ms away. That is a very short time in between events.

Take a look at the WebView Source Code, and just see the onTouchEvent function. It is just impossible for it to be handled by the processor in less than 9ms (Keep on dreaming!!!). That's why you constantly see the "Miss a drag as we are waiting for WebCore's response for touch down." message. The code just can't be handled on time.

How to fix it? First, you can not re-write the onTouchEvent code to improve it, it is just too much. But, you can "mock it" in order to limit the event rate for dragging movements let's say to 40ms or 50ms. (this depends on the processor).

All touch events go like this: ACTION_DOWN -> ACTION_MOVE......ACTION_MOVE -> ACTION_UP. So we need to keep the DOWN and UP movements and filter the MOVE rate (these are the bad guys).

And here is a way to do it (you can add more event types like 2 fingers touch, all I'm interested here is the single finger scrolling).

import android.content.Context;
import android.view.MotionEvent;
import android.webkit.WebView;


public class MyWebView extends WebView{

    public MyWebView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    private long lastMoveEventTime = -1;
    private int eventTimeInterval = 40;

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        long eventTime = ev.getEventTime();
        int action = ev.getAction();

        switch (action){
            case MotionEvent.ACTION_MOVE: {
                if ((eventTime - lastMoveEventTime) > eventTimeInterval){
                    lastMoveEventTime = eventTime;
                    return super.onTouchEvent(ev);
                }
                break;
            }
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_UP: {
                return super.onTouchEvent(ev);
            }
        }
        return true;
    }
}

Of course Use this class instead of WebView and you'll see the difference when scrolling.

This is just an approach to a solution, yet still not fully implemented for all lag cases due to screen touching when using WebView. However it is the best solution I found, at least for my specific needs.

Andrew Barber
  • 37,547
  • 20
  • 91
  • 118
Nate Castro
  • 99
  • 1
  • 1
  • I would like to point out that the webview source code you posted is from 2010 – CQM Nov 05 '12 at 23:41
  • This does not work, it does not smooth scrolling, I can't feel the difference. – neevek Nov 19 '12 at 12:13
  • I have implemented this setting the limit up to 80, but it actually does not seem to improve the performance but it does catch some move events. What does it do for you? – Ragnar Dec 29 '12 at 17:12
  • Have read that a click event is 6 times slower that touch event touchstart. To avoid delays you can use $('#button').on( 'touchstart click', function() { action here; return false; }); – Codebeat Mar 28 '14 at 15:22
  • Also, don't use the click event in your html apps, it adds a 300ms delay to respond on every click, to determine it's a click. Better use touchstart instead. I have made an clickhandler that uses two events and takes the first triggered event. I use 'touchstart click', so it still works without a touchscreen. – Codebeat Apr 24 '15 at 08:02
  • I tried this and weirdly, at least in our test case, a native JS touch library handled this in our WebView better. – J-Boss Sep 04 '15 at 21:13
6

None of those answers was not helpful for me.

Finally I have found reason and solution. The reason was a lot of CSS3 filters (filter, -webkit-filter).

Solution

I have added detection of WebView in web page script in order to add class "lowquality" to HTML body. BTW. You can easily track WebView by setting user-agent in WebView settings. Then I created new CSS rule

body.lowquality * { filter: none !important; }
l00k
  • 1,309
  • 1
  • 15
  • 29
  • Awkward when 5 years later there are very few reasons to use the webview despite devices being faster, more mobile browser compatible performance has greatly improved and other reasons. Thanks for looking into it though! – CQM Oct 21 '16 at 22:11
  • @CQM I had the same problem, I found solution so I wanted to share it :) – l00k Oct 21 '16 at 22:12
  • I'm just being facetious, this is one of my oldest questions, thanks again! – CQM Oct 21 '16 at 22:17
  • 1
    It is absurd that this is an issue in 2016/2017. None of the CSS filters should be challenging for any mobile GPU. – Adam Leggett Jul 25 '17 at 16:21
4

If there's only some few components of your webview that is slow or laggy, try adding this to the elements css:

transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);

This has been the only speedhack that really had a effect on my webview. But be careful not to overuse it! (you can read more about the hack in this article.)

Erex
  • 1,515
  • 1
  • 15
  • 20
3

Try this:

mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
George Maisuradze
  • 1,654
  • 17
  • 16
3

If you are binding to the onclick event, it might be slow on touch screens.

To make it faster, I use fastclick, which uses the much faster touch events to mimic the click event.

Tzach
  • 11,483
  • 11
  • 57
  • 99
  • fastclick is no longer being developed... yes the touch events are slow and I just needed it to work and found with jquery the speed issue can be worked around using `$('#').on('touchstart', function() {...});` as opposed to onclick – CrandellWS Aug 20 '18 at 20:15