WebView想说爱你不容易啊

为什么要使用WebView

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

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

使用

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


  1. <WebView     
  2.  
  3.     android:id="@+id/web_view"     
  4.  
  5.     android:layout_width="match_parent"     
  6.  
  7.     android:layout_height="match_parent"/>  

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

那就是在代码中动态添加。

首先在布局文件中声明一个parent布局


  1. <LinearLayout 
  2.  
  3. android:id="@+id/web_view" 
  4.  
  5. android:layout_width="match_parent" 
  6.  
  7. android:layout_height="wrap_content" 
  8.  
  9. android:orientation="horizontal" 
  10.  
  11. android:scrollbars="none" />  

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


  1. WebView webView = new WebView(context); 
  2.  
  3. webViewLayout.addView(webView);  

网上很多人说这个context应该用application的,我觉得是不对的,如果你的WebView需要弹出一个dialog呢?还有其他的不可预估的问题的,最好还是用当前的activity的Context是最合适的。

上面说的是如何把WebView添加进来进行使用,然后到底它有哪些属性是我们在开发中需要使用到的呢?


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

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


  1. webView.setWebChromeClient(new WebChromeClient() {     
  2.  
  3.      @Override    
  4.  
  5.      public void onProgressChanged(WebView view, int newProgress) { 
  6.  
  7.          //加载的进度 
  8.  
  9.      } 
  10.  
  11.      @Override 
  12.  
  13.      public void onReceivedTitle(WebView view, String title) {    
  14.  
  15.          //获取WebView的标题 
  16.  
  17.      } 
  18.  
  19.     @Override 
  20.  
  21.     public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {     
  22.  
  23.         return super.onJsAlert(view, url, message, result); 
  24.  
  25.         //Js 弹框 
  26.  
  27.     } 
  28.  
  29.     @Override 
  30.  
  31.     public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {    
  32.  
  33.         AlertDialog.Builder b = new AlertDialog.Builder(IllegalQueryActivity.this);     
  34.  
  35.         b.setTitle("删除");     
  36.  
  37.         b.setMessage(message);     
  38.  
  39.         b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {         
  40.  
  41.             @Override         
  42.  
  43.             public void onClick(DialogInterface dialog, int which) {             
  44.  
  45.                 result.confirm();         
  46.  
  47.             }     
  48.  
  49.         });     
  50.  
  51.         b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {         
  52.  
  53.             @Override         
  54.  
  55.             public void onClick(DialogInterface dialog, int which) {             
  56.  
  57.                 result.cancel();         
  58.  
  59.             }     
  60.  
  61.         });     
  62.  
  63.         b.create().show();     
  64.  
  65.         return true; 
  66.  
  67.     } 
  68.  
  69. }); 
  70.  
  71. webView.setWebViewClient(new WebViewClient() {     
  72.  
  73.     @Override     
  74.  
  75.     public boolean shouldOverrideUrlLoading(WebView view, String url) {         
  76.  
  77.        //需要设置在当前WebView中显示网页,才不会跳到默认的浏览器进行显示 
  78.  
  79.        return true;    
  80.  
  81.     }     
  82.  
  83.     @Override     
  84.  
  85.     public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { 
  86.  
  87.         super.onReceivedError(view, request, error); 
  88.  
  89.         //加载出错了 
  90.  
  91.     }    
  92.  
  93.     @Override     
  94.  
  95.     public void onPageFinished(WebView view, String url) {         
  96.  
  97.         super.onPageFinished(view, url); 
  98.  
  99.         //加载完成 
  100.  
  101.     } 
  102.  
  103. }); 
  104.  
  105. webView.setDownloadListener(new DownLoadListener());//下载监听 
  106.  
  107. private class DownLoadListener implements DownloadListener {    
  108.  
  109.     @Override    
  110.  
  111.     public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {       
  112.  
  113.     } 
  114.  
  115. }  

然后就是WebView跟JS的交互了


  1. webView.addJavascriptInterface(new WebAppInterface(this), "WebJs"); 
  2.  
  3. public class WebAppInterface {  
  4.  
  5.     Context mContext;     
  6.  
  7.     public WebAppInterface(Context c) {         
  8.  
  9.         mContext = c;     
  10.  
  11.     }     
  12.  
  13.     @JavascriptInterface     
  14.  
  15.     public void method() { 
  16.  
  17.     } 
  18.  
  19.  
  20. webView.loadUrl("javascript:jsMethod()");//这是WebView最简单的调用JS的方法  

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


  1. @Overrideprotected void onPause() {     
  2.  
  3.     super.onPause();     
  4.  
  5.     if (webView != null) {         
  6.  
  7.         webView.onPause();     
  8.  
  9.     } 
  10.  
  11.  
  12. @Override 
  13.  
  14. protected void onResume() {     
  15.  
  16.     super.onResume();     
  17.  
  18.     if (webView != null) {         
  19.  
  20.         webView.onResume();     
  21.  
  22.     } 
  23.  
  24.  
  25. @Override 
  26.  
  27. protected void onDestroy() {         
  28.  
  29.     if (webView != null) {         
  30.  
  31.         webView.clearCache(true); //清空缓存    
  32.  
  33.         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {             
  34.  
  35.             if (webViewLayout != null) {                 
  36.  
  37.                 webViewLayout.removeView(webView);             
  38.  
  39.             }             
  40.  
  41.         webView.removeAllViews();             
  42.  
  43.         webView.destroy();         
  44.  
  45.     }else {             
  46.  
  47.         webView.removeAllViews();             
  48.  
  49.         webView.destroy();             
  50.  
  51.         if (webViewLayout != null) {                 
  52.  
  53.             webViewLayout.removeView(webView);            
  54.  
  55.         }         
  56.  
  57.      }   
  58.  
  59.      webView = null;     
  60.  
  61.   }    
  62.  
  63. }  

可以看到上面的onDestroy方法中对系统的版本进行了判断,那是因为我在不同的版本中进行了测试,如果低于5.0版本的WebView中,如果先在parent中remove了WebView,那WebView将无法进行destroy了,这样就会造成内存的泄漏,下来你们可以自己去尝试一下这个说法是不是正确的。

现在还遇到的一个问题就是,当WebView嵌套在ScrollView中时,某些机型会出现闪屏的问题,单独WebView的时候是不会出现的,把硬件加速关闭了之后,对用户的体验又不好,所以暂时还未想到比较好的解决方案,所以还是建议不要在ScrollView中嵌套WebView这样的控件。

作者:mehao

来源:51CTO

时间: 2024-10-30 12:02:00

WebView想说爱你不容易啊的相关文章

一位seoer的心声:百度想说爱你不容易

我是从08年开始自己学习建站,我想说:我是个菜鸟,但是菜鸟也有建站的权力.网站对于菜鸟来说是自己的奋斗方向以及对自己努力付出后的一种成就的肯定与展现. 从刚开始的学习html代码,在到后来的asp,我慢慢的开始深入了解了网站建设的魅力与前景.我清楚的记得我的第一个个人主页是在刚上大学那会做的,当时连续通宵了2个晚上做出了10多个页面的全静态网站.很有成就感!但那会根本没有什么SEO,百度都没这么有名,还没上市呢-- 和很多刚入门的站长一样,我以为有了网站就算是成功了.后来发现我的网站根本没什么人

百度文库外链 想说爱你不容易

对于国内做百度优化的SEOer来说都有一个不争的共识,百度总会更加的照顾自家的产品(国内的反垄断意识还不强).对于这个现象我们可以从很多方面看出来,当我们百度一个关键词的时候,经常性的出现在第一的往往是百度自己的产品,如百度知道.百度百科.百度贴吧.百度文库等等 .针对这个现象,很多SEOer都很喜欢通过借助百度产品的外链来提高权重及排名.笔者的站点是教育站点,在做百度文库上很有优势,但是在做了一阶段后,笔者心中的感受是:百度文科,想说爱你不容易. 对于百度文库外链的效果,业内人士一直存在着不同

原创,想说爱你不容易

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 我相信每个站长都希望能够原创,但是又有多少个站长能够原创呢?在这里我就告诉大家一个事实:不是你的能力不行,而是你的网站让你无法原创. 近日,一口气拜读了关于网站推广方面的许多文章,大家都不约而同地提到原创,诸如原创如何重要?怎么来原创?原创怎么起作用?等等.我想了想,原创好是好,但你网站内容能不能原创,就不好说了,这得看你网站是如何定位的.

OpenGL ES 灯光,想说爱你并不是很容易的事

OpenGL ES 灯光,想说爱你并不是很容易的事 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 头疼!!!坚持把这个总结写完吧,要不,明天又得重新疏理一会儿思路才能开始工作......噢,忘

大冰箱,想说爱你不容易

[IT168 厂商动态]在不少人的眼里,大冰箱是冰箱里的"高富帅",与时尚的家居生活完美匹配.可是,实际情况却不尽然.据卡萨帝官方微博开展的一个网络调查显示,拥有大冰箱的用户却并没有享受到卓越的使用体验,相反却遭受着大冰箱带来的很多不便,不少人在面对华丽时尚的大冰箱时只能无奈地叹息:大冰箱,想说爱你不容易!痛点一:体积大 入户难想要买个冰箱竟然还要拆门?一名叫"会飞的鱼"网友在微博上吐槽,"好不容易买个大冰箱,搬到家门口却傻了眼,别说家门,连小区的电梯都进

想说爱你不容易 阿里云OS对比安卓无明显优势

一周前得了一部 阿里云手机,答应写篇评测.但是说实话,手机换了好几部,评测却真没有写过,只好挂着评测的名头来写写阿里云这个系统了.     在这里,我不想过多地去讨论云OS到底和安卓有 多少纠缠和渊源,今天只是想从一个用户最直观的角度,用一家之言,来为它把把脉吧.       1.简约不等于简单     阿里云系统给我的最大感觉就是对安卓做了 大量的减法,"去掉"很多安卓上的功能.     尽管这其中不乏人性化的设计,比如上下滑动关机和解锁.但是显然"简约的美丽"和

王强:谈太阳能网络媒体 想说爱你不容易

中介交易 SEO诊断 淘宝客 云主机 技术大厅 王强谈太阳能网络媒体,想说爱你不容易 当前国际原油价格持续飙升,国内天然气也出现短缺,能源问题已成为世界各国共同关注的重大战略问题.<可再生能源法>的颁布和实施,阐明了我国对节能减排.发展清洁.可再生能源战略的重视.作为可再生能源的主力军,太阳能这个永不衰竭的清洁能源,给能源紧缺问题带来了新的希望.目前太阳能行业正面临着前所未有的发展机遇,吸引了传统的家电巨头也纷纷涉足这个领域,开拓新的发展市场.行业的发展离不开政策.资讯.供求等信息的支持,此时

推拿O2O 想说爱你还不容易

<屌丝男士>第四季最后一集里,乔杉终于圆了"大保健"的梦想,可惜却临阵脱逃.终极原因就是怕有偷拍,名誉会一扫而空.这不禁让身为观众的我深思,如果是在家里享受上门服务的推拿和按摩,乔杉是不是就毫无顾忌了呢?事实上,上门推拿O2O近段时间正呈现火爆趋势,众多创业团队纷纷涌入其中. 与上门洗衣.上门美甲.上门洗车.上门烧菜等门类繁多,且早已形成规模的上门服务相比,上门推拿起步较晚.原因就在于上门推拿涉及到用户的健康和财产安全,再加上涉黄的可能性以及传统意识上的阻碍等,不确定因素太

想说爱你很容易 关键字如何排名百度第一页

如何有步骤提供百度的排名是所以站长在倾心追求的.很多站长都说想说爱你不容易,总在感叹我的网站怎么在百度上收索不到,关键字排名都在几十名之外.但是今天我要和这些站长们说.百度,想说爱你很容易,可以让你的站关键字排名百度第一页.通过以下几点,你也会做到. 1.需要选择合适的域名,最好包含所排名的关键字拼音,北京礼品网网站地址 www.lipin-bj.cn主要针对于礼品,所选择的域名就包括了礼品的拼音 2.合理的网站结构,合理的层次结构.网站采用非动态页面,尽量采用静态页面.或采用伪静态页面可以看看