WebView你所不知道的细节

来源:互联网 发布:房子是用来住的 知乎 编辑:程序博客网 时间:2024/05/22 15:47

WebView的实现主要依靠WebView和WebSettings这两个类来实现。WebView提供容器,WebSetting设置WebView支持的属性。

WebView使用过程中需要注意的地方

1、在实例化WebView的时候尽量不要使用当前Activity的引用。用代码New一个WebView而不是在XML中静态写入
我曾经看到有个哥们利用LeakCanary检测过传入当前Activity引用时是否会出现内存泄露,结果是没有。接着换成Application传入,与之前传入的Activity引用进行对比发现,虽然两者都不会造成内存泄露,但是使用Application要使用Activity时所消耗的内存少20~30MB。所以,建议直接使用Application。

即WebView实例化的时候不要采用这种方式
WebView webView = new WebView(this);
应该采用这种方式
WebView webView = new WebView(App.getContext());

示例:

private WebView webView;webView = new WebView(App.getContext());//一定要设置WebView的LayoutParams,并且值MATCH_PARENT。否则的话就会出现有的网页无法加载的情况webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,        ViewGroup.LayoutParams.MATCH_PARENT));binding.webviewContainer.addView(webView); 

2、WebView资源的释放。页面销毁之前勿忘释放WebView资源。具体释放规则可以看下面这段代码

private void clearWebViewResource(){        if (webView != null){                webView.removeAllViews();                //在5.1上如果不加上这句话就会出现内存泄露。这是5.1的bug         // mComponentCallbacks导致的内存泄漏               ((ViewGroup)webView.getParent()).removeView(webView);        webView.setTag(null);                webView.clearHistory();                webView.destroy();               webView = null;         }}

基于以上介绍提供的Demo示例

xml文件:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:tools="http://schemas.android.com/tools">    <data class=".WebViewBinding">        <import type="android.view.View" />    </data>    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <RelativeLayout            android:id="@+id/title"            android:layout_width="match_parent"            android:layout_height="40dp"            android:background="@android:color/background_dark">            <TextView                android:id="@+id/back"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_centerVertical="true"                android:drawableLeft="@drawable/back"                android:gravity="center"                android:onClick="onClick"                android:text="返回"                android:textColor="@android:color/white"                android:textSize="16sp" />            <TextView                android:id="@+id/close"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_centerVertical="true"                android:layout_marginLeft="10dp"                android:layout_toRightOf="@id/back"                android:gravity="center"                android:onClick="onClick"                android:text="关闭"                android:textColor="@android:color/white"                android:textSize="16sp" />        </RelativeLayout>        <RelativeLayout            android:id="@+id/webview_container"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:layout_below="@+id/title"            tools:context="com.syz.example.webview.WebViewActivity">        </RelativeLayout>    </RelativeLayout></layout>

对应的Activity:

package com.syz.example.webview;import android.app.ProgressDialog;import android.content.Intent;import android.databinding.DataBindingUtil;import android.graphics.Bitmap;import android.net.Uri;import android.os.Build;import android.os.Bundle;import android.support.annotation.RequiresApi;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.KeyEvent;import android.view.View;import android.view.ViewGroup;import android.webkit.WebChromeClient;import android.webkit.WebResourceError;import android.webkit.WebResourceRequest;import android.webkit.WebSettings;import android.webkit.WebView;import android.webkit.WebViewClient;import com.syz.example.App;import com.syz.example.R;import com.syz.example.WebViewBinding;import static com.syz.example.R.id.close;/** * Create By Elven_Shi */public class WebViewActivity extends AppCompatActivity implements View.OnClickListener {    public static final String TAG = "WebViewActivity";    private static final String SERVER_URL = "http://192.168.0.199:8080/mobile";//    private static final String SERVER_URL = "http://baidu.com";    private WebView webView;    private WebViewBinding binding;    private ProgressDialog progressDialog;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        binding = DataBindingUtil.setContentView(this, R.layout.activity_web_view);        webView = new WebView(App.getContext());        //一定要设置WebView的LayoutParams,并且值MATCH_PARENT。否则的话就会出现有的网页无法加载的情况        webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                ViewGroup.LayoutParams.MATCH_PARENT));        binding.webviewContainer.addView(webView);        progressDialog = new ProgressDialog(this);        initView();    }    private void initView() {        binding.close.setVisibility(View.GONE);        WebSettings webSettings = webView.getSettings();        webSettings.setPluginState(WebSettings.PluginState.ON);        webSettings.setDefaultTextEncodingName("utf-8");        webSettings.setLoadWithOverviewMode(true);        webSettings.setJavaScriptEnabled(true);//支持js        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//设置通过js打开新的窗口//        webSettings.setSupportZoom(true);//设置可以支持缩放//        webSettings.setBuiltInZoomControls(false);//支持缩放,出现缩放工具。必须和setSupportZoom配合使用//        webSettings.setUseWideViewPort(true);//扩大比例的缩放        webSettings.setSupportMultipleWindows(false);//是否支持多窗口模式//        webSettings.setDisplayZoomControls(false);//隐藏Zoom缩放按钮//        webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);//提高渲染等级        //自适应屏幕        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);        webSettings.setAppCacheEnabled(true);//启用缓存        webSettings.setDomStorageEnabled(true);//使用localStorage则必须打开        webSettings.setBlockNetworkImage(true);//首先让图片阻塞,不加载图片        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//先加载缓存,在请求网络//        String dir = getDir("database", Context.MODE_PRIVATE).getPath();//        webSettings.setDatabasePath(dir);//设置数据库路径//        webSettings.setGeolocationEnabled(true);//        webSettings.setGeolocationDatabasePath(dir);// 设置地理位置数据库路径//        webSettings.setDatabaseEnabled(true);        webView.loadUrl(SERVER_URL);        //WebChromeClient主要是处理解析,渲染网页等浏览器做的事情。        // WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等        //一般情况下,都是需要设置WebChromeClient的。        setWebChromeClient(webView);        setWebViewClient(webView);    }    private void showProgress() {        progressDialog.show();    }    private void closeDialog() {        progressDialog.cancel();    }    /**     * 使用WebChromeClient     *     * @param webView     */    private void setWebChromeClient(final WebView webView) {        webView.setWebChromeClient(new WebChromeClient() {            @Override            public void onProgressChanged(WebView view, int newProgress) {                // 获得网页的加载进度 newProgress为当前加载百分比                super.onProgressChanged(view, newProgress);                Log.e(TAG, "onProgressChanged>>>" + newProgress);            }            @Override            public void onReceivedTitle(WebView view, String title) {                // 获取网页的title,客户端可以在这里动态修改页面的title                // 另外,当加载错误时title为“找不到该网页”                super.onReceivedTitle(view, title);                Log.e(TAG, "onReceivedTitle>>>" + title);            }        });    }    /**     * 采用WebViewClient     *     * @param webView     */    private void setWebViewClient(final WebView webView) {        webView.setWebViewClient(new WebViewClient() {            @Override            public void onPageStarted(WebView view, String url, Bitmap favicon) {                super.onPageStarted(view, url, favicon);                //页面开始加载时                Log.e(TAG, "onPageStarted---开始加载页面");                showProgress();            }            @Override            public void onPageFinished(WebView view, String url) {                super.onPageFinished(view, url);                Log.e(TAG, "onPageFinished---页面加载结束");                closeDialog();                //页面加载好,再加载图片                webView.getSettings().setBlockNetworkImage(false);            }            /**             * 该方法只有在API 23以上版本才可以使用             * @param view             * @param request             * @param error             */            @RequiresApi(api = Build.VERSION_CODES.M)            @Override            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {                super.onReceivedError(view, request, error);                Log.e(TAG, "网络请求发生错误>>>>>"+error.getDescription());            }            @Override            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {                super.onReceivedError(view, errorCode, description, failingUrl);                // 这里进行无网络或错误处理,具体可以根据errorCode的值进行判断                Log.e(TAG, "网络请求发生错误description>>>" + description);            }            /**             * 该方法只有在API 21以上版本才可以使用             * @param view             * @param request             * @return             */            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)            @Override            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {                Log.e(TAG, "shouldOverrideUrlLoading");                view.loadUrl(request.getUrl().toString());                return true;            }            @Override            public boolean shouldOverrideUrlLoading(WebView view, String url) {                /**                 * 网页跳转:                 * 1.在当前的webview跳转到新连接。在这里可以截获url,根据url判断是否是下载url,还是普通链接                 * 如果是普通链接,则直接调用view.loadUrl(url);并返回true。如果是下载链接,则做出下载处理,并返回false表示不跳转                 *                 * 2.调用系统浏览器跳转到新网页                 * openViewByBrowser();                 */                Log.e(TAG, "old shouldOverrideUrlLoading>>>" + url);                view.loadUrl(url);                return true;            }        });    }    /**     * 利用浏览器打开网页     */    private void openViewByBrowser(String url) {        Uri uri = Uri.parse(url);        Intent intent = new Intent(Intent.ACTION_VIEW, uri);        startActivity(intent);    }    @Override    protected void onDestroy() {        super.onDestroy();        clearWebViewResource();    }    private void clearWebViewResource() {        if (webView != null) {            webView.removeAllViews();            //在5.1的机型上如果不加上这句话就会出现内存泄露。这是5.1的bug            ((ViewGroup) webView.getParent()).removeView(webView);            webView.setTag(null);            webView.clearHistory();            webView.destroy();            webView = null;        }    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.back:                //是否可以继续返回,如果true则返回到上一层页面,如果false则关闭页面                if (webView.canGoBack()) {                    webView.goBack();                    binding.close.setVisibility(View.VISIBLE);                } else {                    finish();                }                break;            case close:                finish();                break;            default:                break;        }    }    /**     * back键执行操作     *     * @param keyCode     * @param event     * @return     */    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {            webView.goBack();            binding.close.setVisibility(View.VISIBLE);            return true;        }        return super.onKeyDown(keyCode, event);    }}

关于效果就不用展示了。AS的屏幕录制需要PS做成gif图片,由于电脑上面没有PS。也懒得下载。就不放gif图片了。放一张截图吧,虽然并没有什么卵用O(∩_∩)O哈哈~
这里写图片描述

最后顺带推荐几篇WebView相关的文章

  • Android Webview总结
  • Android 5.1 Webview 内存泄漏新场景
  • WebView内存泄漏优化之路
  • Android WebView: 性能优化不得不说的事
1 0
原创粉丝点击