在当下的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文件中的描述
".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销毁掉。