WebView的使用与优化

来源:互联网 发布:网络教学本科 编辑:程序博客网 时间:2024/06/07 11:20

文章出处:http://www.dengzhr.com/others/mobile/695

Android中的WebView组件本身就是一个浏览器实现。Android 5.0增强的WebView基于Chromium M37,直接支持WebTRC、WebAudio和WebGL。Chromium M37也包括对Web组件规范的原生支持,如自定义元素、阴影DOM、HTML导入和模板,这意味这开发者可以直接在WebView中使用Polymer和Material设计。

Android系统自带的浏览器其实也是基于开源的WebKit引擎实现的。

一. WebView的常用方法如下:

方法描述void goBack()后退。void goForward()前进。void loadUrl(String url)加载指定URL对应的网页。void loadUrl(String url, Map additionalHttpHeaders)用额外的HTTP头加载指定的URL对应的网页。boolean zoomIn()放大网页。boolean zoomOut()缩小网页。void addJavascriptInterface(Object object, String name)将Java对象置入WebView中。void clearCache(boolean includeDiskFiles)清空缓存。void clearHistory()清空访问历史。Bitmap getFavicon()获取当前网页的favicon图标。String getOriginalUrl()获得当前网页的URL。String getUrl()获得当前网页的URL。int getProgress()获得当前网页的显示进度。String getTitle()获得当前网页的Title。boolean pageDown(boolean bottom)向下滚动视图大小的一半。boolean pageUp(boolean top)向上滚动视图大小的一半。void reload()重新加载当前网页。void zoomBy(float zoomFactor)指定网页缩放大小。void requestFocus()是页面获得焦点。

更详细的WebView API可查看官方文档:http://developer.android.com/reference/android/webkit/WebView.html

二. 申请访问互联网的权限

访问互联网需要申请INTERNET权限。可以在AndroidMainfest.xml文件中增加如下配置:

<uses-permission android:name="android.permission.INTERNET" />

三. 界面布局

WebView界面布局用<WebView>指定。

在activity_main.xml中:

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

四. 从url加载网页

(1)方法一:loadUrl()

在MainActivity.java中,使用loadUrl()访问网页,都是使用Android系统自带或第三方的浏览器来访问。

其中:

1)Web资源:webView.loadUrl("http://dengzhr.com");

2)本地文件用:webView.loadUrl("file:///andoroid_asset/XX.html");
(本地文件存放在assets文件中)

import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.Menu;import android.view.MenuItem;import android.webkit.WebView;public class MainActivity extends AppCompatActivity {    // WebView访问的URL地址    private String url = "http://ce.sysu.edu.cn/hope";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 获取WebView元素        WebView myWebView = (WebView) findViewById(R.id.myWebView);        // 加载url网页        myWebView.loadUrl(url);    }}

(2)方法二: 使用URL Intent访问

使用Intent意图访问:

private String url = "http://ce.sysu.edu.cn/hope";Uri uri = Uri.parse(url);Intent intent = new Intent(Intent.ACTION_VIEW, uri);startActivity(intent);

五. 加载HTML代码

WebView提供了loadData(String data, String mimeType, String encoding)方法,可以对HTML字符进行解析并解析出来。但是loadData()当加载包含中文的HTML内容时,会显示乱码。

loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)是loadData()方法的增强版,不会产生乱码。

WebView myWebView = (WebView) findViewById(R.id.myWebView);String summary = "<html><body>You scored <b>192</b> points.真棒!</body></html>";myWebView.loadData(summary, "text/html", "utf-8");// 或者使用loadDataWithBaseURL() myWebView.loadDataWithBaseURL(null, summary, "text/html", "utf-8", null);

六. 使用WebView中的JavaScript调用Android方法

为了让WebView中的JavaScript脚本调用Android方法,WebView提供了一个配套的WebSettings工具类,该工具类提供了大量的方法来管理WebView的选项设置,其中它的setJavaScriptEnabled(true)即可让WebView中的WebView中的JavaScript脚本来调用Android方法。

为了把Android对象暴露给WebView中的JavaScript代码,WebView提供了addJavaScriptInterface(Object object, String name)方法,该方法负责将object对象暴露给JavaScript中的name对象。

因此,在WebView的JavaScript中调用Android方法只要如下三个步骤:

  • (1) 调用WebView关联的WebSettings的setJavaScriptEnabled(true),启用JavaScript调用功能;
  • (2) 条用WebView的addJavaScriptInterface(Object object, String name)方法,将object对象暴露给JavaScript脚本;
  • (3) 在JavaScript脚本中,通过暴露的name对象调用Android方法。

实例:

MainActivity.java:

// 获取WebView元素对象WebView myWebView = (WebView) findViewById(R.id.myWebView);// 打开远程网页myWebView.loadUrl("http://dengzhr.com/test.html");// 获取WebView的设置对象WebSettings webSettings = myWebView.getSettings();// 开启JavaScript调用webSettings.setJavaScriptEnabled(true);// 将MyObj对象暴露给JavaScript脚本myWebView.addJavascriptInterface(new MyObject(this), "myObj");

MyObject.java:

import android.app.AlertDialog;import android.content.Context;import android.webkit.JavascriptInterface;import android.widget.Toast;public class MyObject {    Context mContext;    MyObject(Context context) {        this.mContext = context;    }    // 该方法将会暴露给JavaScript脚本调用    @JavascriptInterface    public void showToast(String name) {        Toast.makeText(mContext, name + "您好!", Toast.LENGTH_LONG).show();    }    // 该方法将会暴露给JavaScript脚本调用    @JavascriptInterface    public void showList() {        // 显示一个普通的列表对话框        new AlertDialog.Builder(mContext)                .setTitle("图书列表")                .setIcon(R.mipmap.ic_launcher)                .setItems(new String[] {"疯狂Android讲义",                        "Android编程指南",                        "Android和PHP开发实践",                        "Android数据库应用编程"}, null)                .setPositiveButton("确定", null)                .create()                .show();    }}

test.html:

<!DOCTYPE html><html><head>    <meta http-equiv="Content-Type" content=" text/html; charset=utf-8" />    <title>JS调用Android</title>    <style>        input[type=button] {            font-size: 14px;            line-height: 1.8;               background: #249E78;               border: 1px #ccc solid;               color: #fff;               margin: 0 10px;        }    </style></head><body><input type="button" value="打招呼" onclick="myObj.showToast('Hello, World!');" /><input type="button" value="图书列表" onclick="myObj.showList();" /> </body></html>

效果图如下:

此处输入图片的描述

源码下载

此处输入图片的描述

七. 在APP中使用系统自带的浏览器引擎

当用户点击一个WebView中的页面的链接时,通常,是由系统自带的默认浏览器打开并加载目标URL。

但是,我们可以通过webView.setWebViewClient(new WebViewClient())方法来覆盖这一系统默认行为,那么链接就会在WebView中打开。

在WebViewClient主要帮助webView去处理一些页面控制和请求通知。

WebView myWebView = (WebView) findViewById(R.id.myWebView);myWebView.loadUrl("http://ce.sysu.edu.cn/hope");myWebView.setWebViewClient(new WebViewClient() {    @Override    public boolean shouldOverrideUrlLoading(WebView view, String url) {        // 不采用系统默认浏览器加载URL        view.loadUrl(url);        // 当返回true时,控制网页在WebView中打开        // 当返回false时,控制网页在系统自带的或第三方的浏览器中打开        return true;    }});

八. 后退与前进

默认情况下,当你在WebView中依次打开好几个网页时,如果想返回上一个网页,按返回键却会退出整个应用程序。显然,这样的用户体验确实挺糟糕的。

当你的WebView覆盖了URL加载,它会自动生成历史访问记录。你可以通过goBack()或goForward()向前或向后访问已访问过的站点。根据这一点,我们可以改写物理返回按键的返回逻辑,让它返回当前WebView网页栈的前一项即可。

在这里,我们在Activity下改写物理按键的返回逻辑:

// 改写按键的返回逻辑@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {    // 当当前按键为返回键时    if(keyCode == KeyEvent.KEYCODE_BACK) {        // 如果当前WebView存在访问栈        if(myWebView.canGoBack()) {            // 返回页面的上一页            myWebView.goBack();            return true;        }else {            // 如果当前页为最初加载的页面时,则返回键退出程序            System.exit(0);        }    }    return super.onKeyDown(keyCode, event);}

完整的代码如下:

import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.KeyEvent;import android.view.Menu;import android.view.MenuItem;import android.webkit.WebView;import android.webkit.WebViewClient;public class MainActivity extends AppCompatActivity {    private WebView myWebView;    private String myUrl = "http://dengzhr.com";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myWebView = (WebView) findViewById(R.id.myWebView);        myWebView.loadUrl(myUrl);        myWebView.setWebViewClient(new WebViewClient() {            @Override            public boolean shouldOverrideUrlLoading(WebView view, String url) {                // 不采用系统默认浏览器加载URL                view.loadUrl(url);                // 当返回true时,控制网页在WebView中打开                // 当返回false时,控制网页在系统自带的或第三方的浏览器中打开                return true;            }        });    }    // 改写按键的返回逻辑    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        // 当当前按键为返回键时        if(keyCode == KeyEvent.KEYCODE_BACK) {            // 如果当前WebView存在访问栈            if(myWebView.canGoBack()) {                // 返回页面的上一页                myWebView.goBack();                return true;            }else {                // 如果当前页为最初加载的页面时,则返回键退出程序                System.exit(0);            }        }        return super.onKeyDown(keyCode, event);    }}

九. 显示加载网页的进度条

在加载网页的过程中,如果当前网络信号不佳或者网页体积较大,页面会出现较长一段时间的空白。用户有可能在这较长时间的的等待中,以为当前网页无法加载而退出应用。这样,用户体验无疑是不佳的。

网络信号和网页体积都是我们所难以控制的。如果,能在用户等待网页加载的过程中,显示当前加载的进度,用户就能心中有数,并能更好地掌握当前页面的可访问性。为此,我们就需要去判断页面的加载过程,制作进度条给予用户良好的体验效果。

具体如下:

private WebView myWebView;private String myUrl = "http://dengzhr.com";private ProgressDialog dialog;myWebView = (WebView) findViewById(R.id.myWebView);myWebView.loadUrl(myUrl);// 设置在WebView中打开网页myWebView.setWebViewClient(new WebViewClient() {    @Override    public boolean shouldOverrideUrlLoading(WebView view, String url) {        // 不采用系统默认浏览器加载URL        view.loadUrl(url);        // 当返回true时,控制网页在WebView中打开        // 当返回false时,控制网页在系统自带的或第三方的浏览器中打开        return true;    }});// 设置网页加载的进度条显示myWebView.setWebChromeClient(new WebChromeClient() {    @Override    public void onProgressChanged(WebView view, int newProgress) {         /*         *newProgress 为1-100之间的整数         * newProgress = 100时,意味着网页加载完毕         * newProgress < 100时,意味着网页正在加载         **/        if(newProgress == 100) {            // 网页加载完毕,关闭进度提示            closeDialog();        }else {            // 网页正在加载            openDialog(newProgress);        }    }    // 关闭进度条    private void closeDialog() {        if(dialog != null && dialog.isShowing()) {            dialog.dismiss();            dialog =null;        }    }    // 打开进度条,并设置进度条样式    private void openDialog(int newProgress) {        if(dialog == null) {            dialog = new ProgressDialog(MainActivity.this);            dialog.setTitle("正在加载...");            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);            dialog.setProgress(newProgress);            dialog.show();        }else {            dialog.setProgress(newProgress);        }    }});

此处输入图片的描述

源码下载

此处输入链接的描述

十. WebView缓存的运用

使用进度条来提醒用户当前的加载进度确实可以提高用户体验。但这种做法是治标不治本的,网页加载依然缓慢,响应性能依然不够好。

除了对网页进行网络请求加载和文件大小等优化以外,还可以通过使用缓存来减少网络请求,从而加快网页的响应。

WebView中缓存的设置:

1)优先使用缓存:webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

2)不使用缓存:webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

// WebView优先使用缓存加载WebSettings settings = myWebView.getSettings();settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

本文作者:凳子_Joinery,转载请注明出处:http://www.dengzhr.com/others/mobile/695


0 0