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

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

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

《Android编程权威指南》之网页浏览(WebView)篇_第1张图片
图片取自网络

《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控件。


《Android编程权威指南》之网页浏览(WebView)篇_第2张图片
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显示

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

《Android编程权威指南》之网页浏览(WebView)篇_第3张图片
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)篇)