美文网首页view技术干货Android开发
《Android编程权威指南》之网页浏览(WebView)篇

《Android编程权威指南》之网页浏览(WebView)篇

作者: 夜远曦白 | 来源:发表于2016-09-14 15:36 被阅读418次

    有时候项目中会有一些资讯列表,列表展现的是资讯图片、标题、简介、或者各种其他点击量这类信息什么的啊,然后点击列表中的文章或是图片,然后进入一个网页,就是展示具体的文章内容了,当然,这里网页URL在列表数据中由服务器返回的。

    哈哈,就想放张双越的虐dog图,(__) 嘻嘻……

    图片取自网络

    《Android权威编程指南》这里用的是一个PhotoGallery项目来讲解的网页浏览,我这里学习总结就不用那个例子了,麻烦了点,就自己随意弄个url地址,来压缩例子重点知识吧,主要分为两种方式打开网页:

    隐式intent (隐式intent可启动浏览器,并在其中打开图片URL指向的网页)

    核心代码:

    Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
    startActivity(i); 
    

    使用WebView(使用隐式intent打开网页简单又高效,但是,不想打开独立的浏览器的时候,WebView就派上用场了,而且,在真正的项目中,要展现一篇文章的详情,也不可能真的去打开一个浏览器去展示吧,万一用户手机就没有浏览器这类应用软件呢,所以,开始来学习WebView吧,WebView控件等于就是给我们开发应用软件内置了一个浏览器的感觉,我这里弄个简单学习实例Demo,到了真正项目中就灵活运用一下吧)

    WebView要成功显示一个网页要做的事情:

    • 首先——告诉WebView要打开的URL
    • 其次——启用JavaScript。JavaScript默认是禁用的。虽然并不总是需要启用它,可是项目中有时候的HTML页面有些互动需要。(启用JavaScript后,Android Lint会警告信息(担心跨网站的脚本攻击),可以使用@SuppressLint("SetJavaScriptEnabled")注解onCreate(...)方法以禁止Lint的警告。)
    • 最后——覆盖WebViewClient类的shouldOverrideUrlLoading(WebView, String)方法,并返回false值。

    Demo中弄了两个按钮,一个按钮就是使用隐式intent打开网页,按钮点击时间中的核心代码在如上,第二个按钮把url传入了下个页面WebViewActivity.java,使用的WebView打开网页,布局文件中也就放入了一个WebView控件。


    Demo截图

    WebViewActivity .java

    public class WebViewActivity extends AppCompatActivity {
        private WebView mWebView;
        @SuppressLint("SetJavaScriptEnabled")
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_web_view);
            mWebView = (WebView) findViewById(R.id.webview);
            String uri = getIntent().getStringExtra("uri");
            mWebView.getSettings().setJavaScriptEnabled(true);
            mWebView.setWebViewClient(new WebViewClient(){
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                    return false;
                }
            });
            mWebView.loadUrl(uri);
        }
    }
    

    小结:

    • 加载URL必须等WebView配置完成后进行
    • 启动JavaScript——调用getSettings()方法获得WebSettings实例,再调用WebSettings.setJavaScriptEnabled(true)方法
    • WebSetting是修改WebView配置的三种途径之一。另外其他一些可设置属性,如用户代理字符串和显示文字大小。
    • 配置WebViewClient。WebViewClient是一个事件接口。可自己实现WebViewClient来响应各种渲染事件。例如,可检测渲染器何时开始从指定URL加载图片,或决定是否需要向服务器重新提交POST请求。WebViewClient很多方法可覆盖,大多数用不到,必须要覆盖shouldOverrideUrlLoading(WebView, String)默认方法。当有新的URL加载到WebView时,譬如说点击某个链接,该方法会决定下一步行动,即对网页中超链接按钮的响应,如返回true,表示WebView不要处理URL,如返回false,表示叫WebView,去加载这个URL,默认返回false。

    使用WebChromeClient优化WebView显示

    这里给布局添加一个进度条控件

    Demo截图

    代码中声明进度条,给进度条设置mProgressBar.setMax(100);然后使用WebChromeClient,核心代码:

    mWebView.setWebChromeClient(new WebChromeClient(){
                @Override
                public void onProgressChanged(WebView view, int newProgress) {
                    if (newProgress == 100){
                        mProgressBar.setVisibility(View.GONE);
                    }else {
                        mProgressBar.setVisibility(View.VISIBLE);
                        mProgressBar.setProgress(newProgress);
                    }
                }
                @Override
                public void onReceivedTitle(WebView view, String title) {
                    Toast.makeText(WebViewActivity.this, title, Toast.LENGTH_LONG).show();
                }
            });
    

    这样进入网页时,网页加载时,会出现进度条,onReceivedTitle本来是用于模拟显示子标题,Demo中就先打印出来看看title是什么,网页加载完毕会打印title,同时进度条消失。

    小结:

    • WebChromeClient相当于一个事件接口,用来响应那些改变浏览器中装饰元素的事件,包括JavaScript警告信息、网页图标、状态条加载,已经当前网页标题的刷新。
    • onProgressChanged(WebView, int)是进度条更新的回调,onReceivedTitle(WebView, String)是标题栏更新的回调。

    处理WebView的设备旋转问题

    当旋转设备的时候,WebView会重新加载网页,由于WebView包含太多数据,无法在onSaveInstanceState(...)方法中全部保存,所以设备旋转,它必定从头加载网页数据。WebView是视图层级结构的一部分,旋转肯定会销毁重建,那用什么方法解决这个问题呢?答案如下:
    对于一些类似的类(如VideoView),Android文档推荐让activity自己处理设备配置变更,即无法重建activity,就能直接调整自己的视图以适应新的屏幕尺寸。
    在Demo的AndroidManifest.xml中添加如下代码就解决问题了


    Demo截图

    android:configChanges属性表明,若因键盘开关、屏幕方向改变、屏幕大小改变而发生配置改变,则activity应自己处理配置更改。

    注意:

    • 自己处理配置更改,资源修饰符无法自动工作,开发人员必须手工重载视图。
    • activity自己处理配置更改,依然需要覆盖Activity.onSavedInstanceStare(...)方法存储UI状态,因为即使自己处理设备配置更改,低内存情况下的生死还是需要考虑。

    深入学习:注入 JavaScript 对象

    文档网页:https://developer.android.com/reference/android/webkit/WebView.html
    使用addJavaScriptInterface(Object, String)方法可注入任意JavaScript对象到指定文档中。
    自Jelly Bean 4.2(API 17) 开始,只有以@JavascriptInterface注解的公共方法才会暴露给JavaScript。在这之前,所有对象树种的公共方法都是开放访问的。安全起见,要么自己掌控局面,要么严格控制不要暴露自己的接口。

    深入学习:WebView 升级

    KitKat 4.4(API 19)发布的WebView经历了一次大修,新WebView使用了和Android版Chrome一样的渲染引擎。

    WebView终于支持使用 Chrome DevTools进行远程调试了(调用WebView. setWebContentsDebuggingEnabled()方法开启)

    自Lollipop(Android 5.0)开始,WebView的Chromium层会自动从Google Play商店更新。

    Nougat(Android 7.0),WebView的Chromium层又改为直接来自Chrome APK安装包。

    挑战练习:使用后退键浏览历史网页

    题目见书,突然也想起,我们项目中有个详细文章的浏览,可以从中直接进入到另外一篇详细文章,也是一个网页,然后回退直接回退到文章列表了,而没有回退到历史网页,这里来解决一下这个问题,首先覆盖onBackPressed()方法能监控用户是否按了回退建,然后使用WebView.canGoBack()和WebView.goBack()方法来实现这一逻辑,代码如下:

        @Override
        public void onBackPressed() {
            if(wvArticle.canGoBack()){
                wvArticle.goBack();
            }else {
                super.onBackPressed();
            }
        }
    

    挑战练习:非HTTP链接支持

    有时候传入url,万一不是HTTP链接,WebView就会显示一段错误文字,由于我们覆盖了WebViewClient.shouldOverrideUrlLoading(...)方法返回false,这样WebView总是会尝试自己加载URL,所以为了代码的健全性,在加载URI之前,先检测它的scheme,若不是HTTP或者HTTPS,就根据需求做一些其他处理。

    相关文章

      网友评论

        本文标题:《Android编程权威指南》之网页浏览(WebView)篇

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