Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android webview slow performance

I'm writing a game with javascript. This app runs well on my browser (fast), but I have some trouble to run that with android webview.

  1. The time to start the app takes 5s or more (I think that is kind of slow, but maybe that is normal?)
  2. In the menu of the game I have a method like:

    this.showCredits = function() {
    document.getElementById('core-credits-layer').style.display = 'block';
    document.getElementById('core-credits').style.display = 'block';
    var parent = this;
    
    $.ajax({
        url: 'content/credits.html',
        dataType: 'html',
        success: function(data, status, response) {
            var  now = new Date();
            var s = now.getSeconds()-parent.test.getSeconds();
            console.log('success ajax: '+s);
            document.getElementById('core-credits').scrollTop = 0;
            document.getElementById('core-credits').innerHTML = response.responseText;
            console.log('finished');
        },
        error: function() {
            console.error('failed fetch credits');  
        }
    });
    }
    

    So the console log ("finished", last line in success()), comes immediately after clicking the menu "credits". But it can takes 6s (more or less) until I see the the div #core-credits. In my browser, I see #core-credits immediately after clicking. But the 2nd time clicking on that menu point I get the div after 1-2s. I don't now what that is, I don't think so, that is a caching thing, because I get into the success() callback really fast.

Java side:

    public void onCreate(Bundle savedInstanceState)
{
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Context context = this.getApplicationContext();

    SharedPreferences wmbPreference = PreferenceManager.getDefaultSharedPreferences(this);
    boolean isFirstRun = wmbPreference.getBoolean("FIRSTRUN", true);
    if(isFirstRun) {
        this.copyAudioFiles(context);
    }

    WebView mWebView = (WebView) findViewById(R.id.webview);
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.getSettings().setDomStorageEnabled(true);
    mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

    String data = context.getFilesDir().getPath();
    mWebView.getSettings().setDatabasePath(data+"data/"+this.getPackageName()+"/databases/");
    mWebView.getSettings().setAllowFileAccess(true);
    mWebView.setWebChromeClient(new WebChromeClient());
    String data_root = Environment.getExternalStorageDirectory()+"/"
        +this.getPackageName();
    mWebView.loadUrl("file:///android_asset/www/index.html?system=android&" +
        "data_root="+data_root);  
}

I have this performance problems on my virtual tablet device in eclipse and also on my real asus tablet.

Also animations (jquery show('slow')) are sometimes really slow or broken. For example (It is a card game), a player becomes 9 cards with the show('slow') animation, every 2nd or 3rd time I get 3 or 8 cards but not 9^^.

All this things above are working well on browsers like chromium or firefox. I'm working with Android 4.1.

Activate hardware acceleration didn't help. There are various posts about this rendering problem with webview, but only with the hardware accelaration solution, which didn't help.

like image 841
raffis Avatar asked Mar 30 '13 15:03

raffis


People also ask

How can I improve my WebView performance?

I read about how to increase performance of WebView by implementing Caching web resources like JS, CSS and image files. You can also static resources in your native application, and by intercepting the Resource requests you can override the default behaviour of WebView.

How do I disable cache in WebView?

setAppCacheEnabled(false); webview. getSettings(). setCacheMode(WebSettings. LOAD_NO_CACHE);

Is Android WebView deprecated?

This interface was deprecated in API level 12. This interface is now obsolete.

How much time does a UI thread have to render a screen?

UI Rendering is the act of generating a frame from your app and displaying it on the screen. To ensure that a user's interaction with your app is smooth, your app should render frames in under 16ms to achieve 60 frames per second (why 60fps?).


3 Answers

Forget about HW acceleration in this case - it's a false friend. In most cases it's even slower than software rendering.

But there are many small things you can optimise:

Write faster javascript

  • Always use selector caching, where applicable (there should be only a single occurence of document.getElementById('core-credits') in your code
  • Group / decouple (see next point or use setTimeout directly) code execution and DOM manipulation (which always triggers redraws on single elements or - even worse - a reflow of the document)
  • In some apps i saw good results using the requestAnimationFrame Polyfill for dom manipulations - won't necessarily lead to a higher framerate, but in my case it allowed me to properly "fling" an openlayers map (instead of the device just not reacting to the touchmove)

Be Android friendly

  • Just like intel appframework (formerly jqmobi ui) does, make heavy use of css3 transformations rather than trying to jquery-style "tick" animations
  • Removing border-radius and instead utilising a transparent png approach
  • Other costly renderings on Android are supposed to be: (-webkit-)box-shadow, text-shadow and all kinds of gradients (which again one can exchange for old-school png's)

Hope this helps - will try to elaborate more, resp. rectify information as i continue to fight android webview sluggishness in my own apps currently.

like image 89
Philzen Avatar answered Sep 16 '22 23:09

Philzen


Having gone through the process of developing several apps using Hybrid Mobile App frameworks in HTML5/JS on Android, i'm afraid there isn't a silver bullet that will fix all performance issues. Generally speaking, Javascript performance is not the problem, the problem is frequent and maybe even wasteful changes/modifications to the DOM and a over-use of CSS3 effects which slow the FPS down like box-shadow on Android.

Something which might help, is to use CrossWalk as your WebView rather than the stock WebView component. This means you can get the latest version of Chrome inside your app without having to rely on older versions of the system WebView component. You should observe a performance and stability improvement as you can gain all the benefits of the software improvements to WebKit.

https://crosswalk-project.org

Secondly, consider using a framework which avoids frequent changes to the DOM like React which has a virtual DOM.

http://facebook.github.io/react/

React isn't the only framework to provide this and there are other solutions which aim to provide performance improvements in this area like Famous.

http://famous.org

Lastly, choosing your frameworks to build your app on top of is for me, the most important step. Despite all the investment in improving performance of browsers, they all vary in performance in different areas, so best to hedge your bets at the beginning and pick frameworks which suit the problem you are trying to solve.

Appreciate you may have moved on from this, so hoping this advice will help others.

#lovejavascript, #hatebrowsers

like image 27
Daniel Maclean Avatar answered Sep 20 '22 23:09

Daniel Maclean


did you enable hardware accelaration in your manifest?: http://developer.android.com/guide/topics/graphics/hardware-accel.html ?

like image 30
Mikael Avatar answered Sep 17 '22 23:09

Mikael