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
- WebView你所不知道的细节
- WebView你可能不知道的细节
- [Android] 你所不知道的drawable的那些细节
- Android 禁止ViewPager滑动,你所不知道的细节
- Android 禁止ViewPager滑动,你所不知道的细节
- 你所不知道的 CSS 滤镜技巧与细节
- 你所不知道的 CSS 滤镜技巧与细节
- java线程两种实现方式的区别,你所不知道的小细节
- java线程两种实现方式的区别,你所不知道的小细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- Android Context完全解析,你所不知道的Context的各种细节
- 51nod 1525 并查集
- Java反射
- sshd无法启动——Bad configuration option:ForwardX11Trusted
- 解决coccoapods 导入AFNetworking 真机运行报错 Undefined symbols for architecture arm64:
- 基于C++的RandomForest随机森林总结
- WebView你所不知道的细节
- Lucene实践(一):全文检索的基本原理
- 测试公司网络环境
- Activity解析
- mac终端显示【当前进程已完成】
- 接口调用以及memcache的使用
- 重新认识Eclipse--快捷键
- java-面向对象-面试题《下》
- 销售凭证中的几个日期