美文网首页AndroidAndroidandroid开发
WebView想说爱你不容易啊

WebView想说爱你不容易啊

作者: Me豪 | 来源:发表于2016-12-21 12:04 被阅读2194次
为什么要使用WebView

随着app业务的不断深入发展,只靠着原生代码来堆砌功能是不现实,毕竟开发的时长会增加,而且同时需要开发iOS和Android两套,并且,如果在UI上改变了一丁点,都需要提包(虽然Android现在可以进行热更新,但是热更新不是100%能生效的,其中的原理只要了解过的人都会知道的),最终我们会选择使用原生嵌套H5的方式进行开发,这样,既可以随时更改UI,也可以无限制的进行功能扩展,然后,我们就要使用到Android的WebView了,这个让我们痛并快乐着的控件。

现在的手机高度定制,多多少少都会对系统原生的代码进行了修改和添加的,不同的手机的WebView呈现出来的效果也是不同的,可以说是五彩缤纷了,所以我懂Android开发者的痛苦。接下来我就具体去讲解我在项目中使用WebView的经验,不喜勿喷哈。

使用

一开始相信大家都是直接在布局文件中添加WebView控件,当然我一开始也是这样做的,就是为了简单,而且也不知道这样会出现什么问题。

 <WebView    
     android:id="@+id/web_view"    
     android:layout_width="match_parent"    
     android:layout_height="match_parent"/>

直接就这样添加了一个WebView,发现也没什么问题啊,一样可以显示,什么都是正常的啊。在重复打开有WebView的页面时,你会发现,应用的内存会不断升高,销毁了之后也不会降下来,点击GC也降不下来,这样就出现了内存泄漏了,这时你就会发现,这样使用WebView是不正确的,那么最好方式是如何使用呢?
那就是在代码中动态添加。
首先在布局文件中声明一个parent布局

<LinearLayout    
    android:id="@+id/web_view"   
    android:layout_width="match_parent"    
    android:layout_height="wrap_content"
    android:orientation="horizontal"   
    android:scrollbars="none" />

然后在代码中,把WebView当做其子View添加进去

WebView webView = new WebView(context);
webViewLayout.addView(webView);

网上很多人说这个context应该用application的,我觉得是不对的,如果你的WebView需要弹出一个dialog呢?还有其他的不可预估的问题的,最好还是用当前的activity的Context是最合适的。
上面说的是如何把WebView添加进来进行使用,然后到底它有哪些属性是我们在开发中需要使用到的呢?

webView.loadUrl("www.baidu.com");//WebView加载的网页使用loadUrl
WebSettings webSettings = webView.getSettings();//获得WebView的设置
webSettings.setUseWideViewPort(true);// 设置此属性,可任意比例缩放
webSettings.setLoadWithOverviewMode(true);//适配
webSettings.setJavaScriptEnabled(true);  //支持js
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);  //设置 缓存模式
webSettings.setDomStorageEnabled(true);// 开启 DOM storage API 功能
webSettings.setDatabaseEnabled(true);//开启 database storage API 功能
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);//HTTPS,注意这个是在LOLLIPOP以上才调用的
webSettings.setAppCacheEnabled(true);//开启 Application Caches 功能
webSettings.setBlockNetworkImage(true);//关闭加载网络图片,在一开始加载的时候可以设置为true,当加载完网页的时候再设置为false

上面是使用WebView中最基础的设置,相信在开发过程中都会进行如上的设置的。

webView.setWebChromeClient(new WebChromeClient() {    
     @Override   
     public void onProgressChanged(WebView view, int newProgress) {
         //加载的进度
     }
     @Override
     public void onReceivedTitle(WebView view, String title) {   
         //获取WebView的标题
     }
    @Override
    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {    
        return super.onJsAlert(view, url, message, result);
        //Js 弹框
    }
    @Override
    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {   
        AlertDialog.Builder b = new AlertDialog.Builder(IllegalQueryActivity.this);    
        b.setTitle("删除");    
        b.setMessage(message);    
        b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {        
            @Override        
            public void onClick(DialogInterface dialog, int which) {            
                result.confirm();        
            }    
        });    
        b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {        
            @Override        
            public void onClick(DialogInterface dialog, int which) {            
                result.cancel();        
            }    
        });    
        b.create().show();    
        return true;
    }
});
webView.setWebViewClient(new WebViewClient() {    
    @Override    
    public boolean shouldOverrideUrlLoading(WebView view, String url) {        
       //需要设置在当前WebView中显示网页,才不会跳到默认的浏览器进行显示
       return true;   
    }    
    @Override    
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
        //加载出错了
    }   
    @Override    
    public void onPageFinished(WebView view, String url) {        
        super.onPageFinished(view, url);
        //加载完成
    }
});
webView.setDownloadListener(new DownLoadListener());//下载监听
private class DownLoadListener implements DownloadListener {   
    @Override   
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {      

    }
}

然后就是WebView跟JS的交互了

webView.addJavascriptInterface(new WebAppInterface(this), "WebJs");
public class WebAppInterface { 
    Context mContext;    
    public WebAppInterface(Context c) {        
        mContext = c;    
    }    
    @JavascriptInterface    
    public void method() {
    }
}
webView.loadUrl("javascript:jsMethod()");//这是WebView最简单的调用JS的方法

当activity执行生命周期的时候,这里需要注意的是在onDestroy的时候,需要销毁WebView,不然也会出现内存泄漏的。

@Overrideprotected void onPause() {    
    super.onPause();    
    if (webView != null) {        
        webView.onPause();    
    }
}
@Override
protected void onResume() {    
    super.onResume();    
    if (webView != null) {        
        webView.onResume();    
    }
}
@Override
protected void onDestroy() {        
    if (webView != null) {        
        webView.clearCache(true); //清空缓存   
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {            
            if (webViewLayout != null) {                
                webViewLayout.removeView(webView);            
            }            
        webView.removeAllViews();            
        webView.destroy();        
    }else {            
        webView.removeAllViews();            
        webView.destroy();            
        if (webViewLayout != null) {                
            webViewLayout.removeView(webView);           
        }        
     }  
     webView = null;    
  }   
}
可以看到上面的onDestroy方法中对系统的版本进行了判断,那是因为我在不同的版本中进行了测试,如果低于5.0版本的WebView中,如果先在parent中remove了WebView,那WebView将无法进行destroy了,这样就会造成内存的泄漏,下来你们可以自己去尝试一下这个说法是不是正确的。

现在还遇到的一个问题就是,当WebView嵌套在ScrollView中时,某些机型会出现闪屏的问题,单独WebView的时候是不会出现的,把硬件加速关闭了之后,对用户的体验又不好,所以暂时还未想到比较好的解决方案,所以还是建议不要在ScrollView中嵌套WebView这样的控件。
暂时就总结了这么多,相信以后在项目中还会遇到更多的问题的,遇到其他的问题再更新上来,以备忘吧。


相关文章

  • WebView想说爱你不容易啊

    为什么要使用WebView 随着app业务的不断深入发展,只靠着原生代码来堆砌功能是不现实,毕竟开发的时长会增加,...

  • 想说爱你不容易

    想说爱你不容易 想说爱你不容易 想说爱你不容易 ………………… 想说爱你不容易,我的父亲母亲! 你们每天拼命地挣钱...

  • 画画――想说爱你不容易

    画画――想说爱你不容易 好久没画画了,放弃比坚持容易啊!

  • 2017-05-22

    跑步,想说爱你不容易

  • 床啊,想说爱你不容易

    最近一直想改变作息规律,执行早睡早起计划(其实早睡是针对现代人的标准,这里的早睡相当于古人的晚睡了)。 早起,倒是...

  • 中医啊,想说爱你不容易!

    中医啊,想说爱你不容易! 根据资料显示,在我国,近几年过敏性鼻炎发病率明显增多,地域明显扩大,在北...

  • 卡啊,想说爱你不容易

    1 如今,瑜伽已经成为最普遍的一种健身方式,听说练瑜伽不仅强身健体,柔软线条,提升魅力,还能很好的稳定神经系统,有...

  • 妈妈,想说爱你不容易啊!

    我很爱妈妈,虽然不在她身边,也是每天一个电话的,今年春节回家,我居然发现妈妈心眼有点坏,真的,就是那种特别讨厌的在...

  • 想说读书不容易

    记得有句歌词叫"想说爱你不容易",可是在如今看来,想说爱你很容易,张口就来。要我说,想说读书不容易,撇开手机...

  • 英语啊英语,想说爱你不容易

    英语啊英语,想说爱你不容易 选自《天机乍泄》 钱瑞甫 词曰:死记硬背何时了,单词知多...

网友评论

  • Silicon_Valley:楼主遇到过这种问题没得,webview加载一个网页,但是竟然会自动重定向另一个页面
  • tmyzh:实际操作了一下代码 主要是onDestory里面那一段,首先我没有碰到内存不断升高的现象 可能是页面代码元素过少,然后是我加了onDestory里面那段代码之后 ,不断cg也没有比之前降低的情况 ,有没有哪个大神在实操之后给个对比图
  • 无尽bug伴不眠:建议使用腾讯的X5内核webView 不会有内存泄漏问题
    嘿_87bb:唯一的缺点就是 横屏播放视频的时候 下面会有个QQ浏览器的超链 不知道大神们有没有解决方案可以去掉
  • codeKeeper:webView.clearCache(true);这个执行之后会导致webview每次启动加载页面耗时变长的。
  • urnotxx:受教了 :+1:
  • 56d6d22d2d9e:请问大神,我的webview放到LinearLayout里页面不呈现白屏一般是哪里出的问题:disappointed_relieved:
    Me豪: @灰鹰 你试一下动态添加webview,而且这个linearlayout不要有其他的子view
    56d6d22d2d9e:@Me豪 对,布局内直接放webview并初始化就能呈现页面,布局内放LinearLayout添加webview控件就是白屏,我觉得应该是我哪里忽略了吧,不知道大神能不能想到什么细节提点我一下
    Me豪: @灰鹰 你的意思说放在LinearLayout里面不呈现吗?
  • 匡风含情:謝謝分享~
    KingofGlory:我测试了一下,目前没有发现内存泄露了。请问下,你是怎么发现 “如果低于5.0版本的WebView中,如果先在parent中remove了WebView,那WebView将无法进行destroy了” 这个问题的?
    KingofGlory:文章写得很实用。之前一直没有找到防止内存泄露方法,还想着用多进程的办法来避免。onDestroy()方法里面执行的代码你有测试过吗?
    Me豪:@倪神州 一起学习!

本文标题:WebView想说爱你不容易啊

本文链接:https://www.haomeiwen.com/subject/volqvttx.html