在当下的Android开发中,Webview的身影随处可见,尤其是在Hybrid app中,更是不可或缺,而Webview的性能却是有待改善的。

Webview好用归好用,方便归方便,但是它的性能却比native差了不少,这点大家很容易的在其他App中打开一个Webview页面就能感受到,从点击到页面完全展示出来,普遍都是2,3秒甚至更久(网络好的情况下)。

刚好最近组长说要优化一下Webview,而刚好美团的技术团队又发了一篇很好的文章美团的Webview优化总结,当我一脸傲娇的向组长推荐这篇文章的时候,组长一脸平淡的说“我看过了…”

总的来说要加快Webview的加载速度,App端能够做的事情其实就只有两条路子, 其一是App启动后提前加载一个全局的Webview,等到要用的时候直接拿过来用;其二是点击打开Webview时,同时去做其他需要的网络的请求。

而我们选择是提前加载一个全局的Webview,上代码:

//在自定义的webview中加上一个单例方法
public static MyWebView getInstance(Context context){
        if(myWebView == null){
            myWebView = new myWebView(context);
        }
        return myWebView;
    }
//在自定义的Application的onCreate中初始化一个全局的Webview
@Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        mInstance = this;
//判断当前进程是否主进程,在主进程中打开一个EmptyActivity
    if(SysUtils.isMainProcess(getApplicationContext())){
        mainPrecessInit();
        Intent intent = new     Intent(this,EmptyActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
//判断是否:web进程,在:web进程中初始化全局webview
        if(SysUtils.isRunProcess(this, "com.edison.hehe:web")){
            //web process
            MyWebView.getInstance(getApplicationContext());
            return;
        }

        // *****************************
    }

上面的代码中在主进程中start一个EmptyActivity是干嘛用呢?上代码:

//EmptyActivity的全部代码
public class EmptyActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        finish();
    }

}
//EmptyActivity在Mainfest文件中的描述
<activity
   android:name=".ui.activity.EmptyActivity"
   android:label="@string/title_activity_empty"
   android:process=":web"
   android:theme="@style/AppThemeTransparent"/>

是的,start EmptyActivity的唯一目的是开启一个:web的进程,然后在这个:web进程中去初始化全局的Webview,这样做的好处是不会阻塞了主进程。

最后是要清理Webview的历史数据(上一页记录)

private class WebViewClientImpl extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            mWebSettings.setBlockNetworkImage(true);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            //这里必须要,不然回退有问题.
            if(mClearHistry){
            //mClearHistry在用到Webview的Activity的onCreate中设为true
                mClearHistry = false;
                view.clearHistory();
            }
            mWebSettings.setBlockNetworkImage(false);
        }

        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {}

    @Override
    public void onBackPressed() {}


    }

重写WebViewClient中的onPageFinished方法,加上clearHistory()。
我看到也有同学说clearHistoty方法不管用,具体可以看看这篇WebView无法清理当前页面历史记录

到此,提前加载一个全局的Webview也就完成了,但这样做是容易出现内存泄漏的,这就需要在合适的位置(比如退出app的时候,具体要看业务而定了)把这个Webview销毁掉。