×

深入理解WebView

消耗积分:1 | 格式:rar | 大小:0.6 MB | 2017-10-11

分享资料个

摘要
  作为Android开发者,我们都知道在手机中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装为一个叫做 WebView 组件。今天就为大家讲讲Android中WebView的详细使用方法。
  作为Android开发者,我们都知道在手机中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装为一个叫做 WebView 组件。
  在开发过程中应该注意几点:
  1.这是最基本的 AndroidManifest.xml 中必须添加访问网络权限。
  2.如果访问的页面中有 Java,则 WebView 必须设置支持 Java。
  WebView.getSettings().setJavaEnabled(true);
  3.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 WebView的WebViewClient对象。
  mWebView.setWebViewClient(newWebViewClient(){ publicbooleanshouldOverrideUrlLoading(WebView view, String url){ view.loadUrl(url); returntrue; } });
  4.如果不做任何处理 ,浏览网页,点击系统“Back”键,整个 Browser 会调用 finish()而结束自身,如果希望浏览的网页回退而不是推出浏览器,需要在当前Activity中处理并消费掉该 Back 事件。(代码有些精简)
  publicboolean onKeyDown(intkeyCode, KeyEvent event) { if((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) { mWebView.goBack(); returntrue; } returnsuper.onKeyDown(keyCode, event); }
  与js互调
  既然可以显示网页,那么当然也可以让网页操作本地方法。(由于一行写不下,缩进我调整了一下)
  publicclassWebViewDemoextendsActivity{privateWebView mWebView; privateHandler mHandler = newHandler(); publicvoidonCreate(Bundle icicle) { setContentView(R.layout.WebViewdemo); mWebView = (WebView) findViewById(R.id.WebView); WebSettings webSettings = mWebView.getSettings(); webSettings.setJavaEnabled(true); mWebView.addJavaInterface(newObject() { publicvoidclickOnAndroid() { mHandler.post(newRunnable() { publicvoidrun() { mWebView.loadUrl(“java:wave()”); } }); } }, “demo”); mWebView.loadUrl(“file:///android_asset/demo.html”); } }
  我们看 addJavaInterface(Object obj,String interfaceName)这个方法 ,该方法将一个java对象绑定到一个java对象中,java对象名就是 interfaceName(demo),作用域是Global.这样初始化 WebView 后,在WebView加载的页面中就可以直接通过java:window.demo访问到绑定的java对象了。 来看看在html中是怎样调用的。
  《html》《language=“java”》functionwave(){document.getElementById(“droid”).src=“android_waving.png”; } 《/》《body》《aonClick=“window.demo.clickOnAndroid()”》《imgid=“droid”src=“android_normal.png”mce_src=“android_normal.png”/》《br》Click me! 《/a》《/body》《/html》
  这样在 java 中就可以调用 java 对象的 clickOnAndroid()方法了,同样我们可以在此对象中定义很多方法(比如发短信,调用联系人列表等手机系统功能),这里 wave()方法是 java 中调用 java 的例子。
  需要说明一点:addJavaInterface方法中要绑定的Java对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用 Handler 的目的。
  深入使用WebView
  让js调用Android代码
  首先简述 WebView、WebViewClient、WebChromeClient 之间的区别:
  在 WebView 的设计中,不是什么事都要 WebView类干的,有些杂事是分给其他人的,这样 WebView 专心干好 自己的解析、渲染工作就行了.WebViewClient 就是帮助 WebView 处理各种通知、请求事件等 ,WebChromeClient 是辅助 WebView 处理 Java 的对话框,网站图标,网站 title.
  功能实现:
  利用 android 中的 WebView 加载一个 html 网页,在 html 网页中定义一个按钮,点击按钮弹出一 个 toast.
  实现步骤:
  首先定义一个接口类,将上下文对象传进去,在接口类中定义要在 js 中实现的方法。
  接着在assets资源包下定义一个 html 文件,在文件中定义一个 button.button 的点击事件定义为一个 js 函数。
  之后在 xml 中定义一个 WebView 组件,在活动类中获取 WebView 并对 WebView 参数进行设置,此处特别注意要设置 WebView 支持 js 且将定义的 js 接口类添加到 WebView 中去,此后在 js 中就可以利用该接口类中定义的 函数了。即:
  myWebView.getSettings().setJavaEnabled(true); myWebView.addJavaInterface(newJavainterface(this),”android”);
  最后利用 WebView 加载本地 html 文件的方法是:
  myWebView.loadData(htmlText,“text/html”, “utf-8”);
  此处的htmltext 是以字符串的方式读取 assets 报下 html中的内容。
  4.实现利用返回键返回到上一页:
  设置 WebView 的按键监听,监听到期返回键并判断网页是否能够返回 ,利用 WebView 的 goBack()返回到上一页。
  WebView 缓存
  在项目中如果使用到 WebView 控件,当加载 html 页面时,会在/data/data/包名目录下生成 database 与 cache 两个文件夹(我的手机没有root,就不截图了)。
  请求的 url 记录是保存在 WebViewCache.db,而 url 的内容是保存在 WebViewCache 文件夹下。 大家可以自己动手试一下,定义一个html文件,在里面显示一张图片,用WebView加载出来,然后再试着从缓存里把这张图片读取出来并显示 。
  WebView 删除缓存
  其实已经知道缓存保存的位置了,那么删除就很简单了,获取到这个缓存,然后删掉他就好了。
  //删除保存于手机上的缓存privateintclearCacheFolder(File dir,longnumDays) { intdeletedFiles = 0; if(dir!= null&& dir.isDirectory()){ try{ for(File child:dir.listFiles()){ if(child.isDirectory()) { deletedFiles += clearCacheFolder(child, numDays); } if(child.lastModified() 《 numDays) { if(child.delete()) { deletedFiles++; } } } } catch(Exception e) { e.printStackTrace(); } } returndeletedFiles; }
  是否启用缓存功能也是可以控制的
  //优先使用缓存: WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //不使用缓存: WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
  在退出应用的时候加上如下代码,可以完整的清空缓存
  File file= CacheManager.getCacheFileBaseDir(); if(file!= null && file.exists() && file.isDirectory()) { for(File item : file.listFiles()) { item.delete(); } file.delete(); } context.deleteDatabase(“WebView.db”); context.deleteDatabase(“WebViewCache.db”);
  WebView 处理 404 错误
  显示网页还会遇到一个问题,就是网页有可能会找不到,WebView当然也是可以处理的(代码如果全部贴出来实在太多了,这里就只贴重要部分了)
  publicclassWebView_404extendsActivity{privateHandler handler = newHandler() { publicvoidhandleMessage(Message msg) { if(msg.what==404) {//主页不存在//载入本地 assets 文件夹下面的错误提示页面 404.html web.loadUrl(“file:///android_asset/404.html”); }else{ web.loadUrl(HOMEPAGE); } } }; @OverrideprotectedvoidonCreate(Bundle savedInstanceState) { web.setWebViewClient(newWebViewClient() { publicbooleanshouldOverrideUrl(WebView view,String url) { if(url.startsWith(“http://”) && getRespStatus(url)==404) { view.stopLoading(); //载入本地 assets 文件夹下面的错误提示页面 404.html view.loadUrl(“file:///android_asset/404.html”); }else{ view.loadUrl(url); } returntrue; } }); newThread(newRunnable() { publicvoidrun() { Message msg = newMessage(); //此处判断主页是否存在,因为主页是通过 loadUrl 加载的,//此时不会执行 shouldOverrideUrlLoading 进行页面是否存在的判断 //进入主页后,点主页里面的链接,链接到其他页面就一定会执行shouldOverrideUrlLoading 方法了 if(getRespStatus(HOMEPAGE)==404) { msg.what = 404; } handler.sendMessage(msg); }).start(); } }
  判断 WebView 是否已经滚动到页面底端
  在View中有一个getScrollY()方法,可以返回当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离。
  还有getHeight()或者 getBottom()方法都返回当前 View 这个容器的高度
  在ViewView中还有getContentHeight() 方法可以返回整个 html 页面的高度,但并不等同于当前整个页面的高度 ,因为 WebView 有缩放功能。你可以通过如下代码来启动或关闭webview的缩放功能。
  mWebView.getSettings().setSupportZoom(true);mWebView.getSettings().setBuiltInZoomControls(true);
  所以当前整个页面的高度实际上应该是原始 html 的高度再乘上缩放比例。 因此,更正后的结果 ,准确的判断方法应该是:
  // 如果已经处于底端if(WebView.getContentHeight*WebView.getScale()-(webvi ew.getHeight()+WebView.getScrollY())){ //XXX}
  WebView获取服务器中的 session 问题
  接下来我们讲如下两个问题:
  Android 中的 WebView 如何获取服务器页面的 jsessionid 的值Android 的 WebView 又是如何把得到的 jsessionid 的值在 set 到服务器中,一致达到他们在同一个 jsessionid 的回话中。
  其实非常非常简单,只不过是几个方法罢了:
  CookieManager cm = CookieManager.getInstance(); cm.removeAllCookie();cm.getCookie(url);cm.setCookie(url, cookie);
  另外还有个 CookieSyncManager,也许你会在一些旧的项目中看到它。从名字来理解,它实际上应该是一个异步缓存器。不过我们看到这个方法已经被标记为过时了,查看源码可以看到过时原因是现在WebView已经是自动的异步缓存了,所以这个类已经没有存在的意义了。 CookieSyncManager
  WebView清除本地cookies
  首先,要清除肯定要会添加,这里给大家提供一个工具方法:
  /*** * 如果用户已经登录,则同步本地的cookie到webview中 */publicvoidsynCookies() { if(!CacheUtils.isLogin(this)) return; CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.removeSessionCookie();//移除String cookies = PreferenceHelper.readString(this, AppConfig.COOKIE_KEY, AppConfig.COOKIE_KEY); KJLoger.debug(cookies); cookieManager.setCookie(url, cookies); CookieSyncManager.getInstance().sync(); }
  在使用网页版淘宝或百度登录时,WebView会自动登录上次的帐号!(因为WebView 记录了帐号和密码的cookies) 所以,需要清除 SessionCookie也是有必要的。
  那么CookieManager同样也为我们提供了清除cookie的方法
  CookieManager.getInstance().removeSessionCookie();
  这里顺便说一下WebView本身也是会记录html缓存的,上一篇博客中我讲了一种通过文件操作去清理缓存的方法,后来我又发现,其实webview本身就提供了清理缓存的方法,其中参数true是指是否包括磁盘文件也一并清除,传true就和我们昨天的讲的效果是一样的了:
  webview.clearCache(true);webview.clearHistory();
  讲一个案例
  讲了这么多的理论知识,最后讲一个使用案例。WebView在实际使用中可以分为两种使用方法,第一种就是类似于QQ微信那种,使用loadUrl直接去显示一个链接,这种方式太简单了,传一个url就行,我就不多说了。
  那么需要详细讲的是第二种,类似的实现大家可以看看开源中国客户端,网易新闻客户端,爱看博客,等客户端的实现方式,它们实际上也是通过webview来显示的一个网页内容,但是并不是单纯的loadurl,而是以字符串的形式去加载一个已经获取到了的html源代码。这样做的好处在于显示的页面可以完全的根据自己喜好来定义,比如我想在末尾添加一张图片,那么简单,在这个html字符串的末尾插入一个img标签就可了。至于使用方法,其实我们在上一篇博客的时候有提到过:
  myWebView.loadData(htmlText,”text/html”, “utf-8”);
  其中htmltext就是我们需要加载的html字符串,使用这个方法可以直接将这个字符串作为网页来显示。
  最后总结一下两种方法的适用场景,前一种载入链接的方法适合一个界面(Activity或Fragment)只有一个WebView或者说WebView占很大一块的时候,同时我们要显示的内容是未知的,那么自然是使用loadurl方法更合适,例如QQ聊天的时候对方发送一条链接,当QQ解析出这个文本是一个网址时就通过webview去加载它。而后一种则适合于定制化内容,一般是那种你可以明确的制度网页内容以及要显示的内容时使用,至于好处就是上面说的,定制性要好很多。
 

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !