WebView core usage and best practices, avoid common pitfalls and optimization techniques

WebView core usage and best practices, avoid common pitfalls and optimization techniques

Introduction to WebView

WebView is a control used to display web content in the Android platform. It is based on the Chromium project (not the full version of the Chrome browser, and does not include all the features in Chrome). WebView uses the WebKit engine to render web pages, which is well compatible with Web standards. It can display content such as HTML, CSS, and JavaScript. It can also be used to dynamically load web content and interact with web pages, such as clicking links and entering text.

WebView is very useful in Android application development, in scenarios where you need to display web content or interact with web pages. For example, in applications such as WeChat or Weibo, WebView is often used to open shared hyperlinks within the application. Displaying web content directly in the application through WebView provides a richer user experience.

WebView life cycle:

  1. onResume() : This method is called back when WebView is active. WebView can execute the response of the web page normally, including loading web page content, executing JavaScript, etc.
  2. onPause() : This method is called back when WebView is switched to the background or loses focus. WebView will pause all ongoing actions, such as DOM parsing, CSS and JavaScript execution, to reduce CPU power consumption.
  3. destroy() : This method is called when the WebView needs to be destroyed to release resources. At this stage, you should ensure that all resources related to the WebView are properly cleaned up to avoid memory leaks.

In order to properly manage the life cycle of WebView, you should call the life cycle methods of WebView following the life cycle methods of Activity. For example, when the Activity enters the onResume state, you should call the onResume method of WebView; when the Activity enters the onPause state, you should call the onPause method of WebView; when the Activity is destroyed, you should ensure that WebView is also destroyed correctly.

 @Override protected void onResume() { super.onResume(); //恢复webview的状态(不靠谱) webView.resumeTimers(); //激活webView的状态,能正常加载网页webView.onResume(); } @Override protected void onPause() { super.onPause(); //当页面被失去焦点被切换到后台不可见状态,需要执行onPause //通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。 webView.onPause(); //当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview //它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。(不靠谱) webView.pauseTimers(); } @Override protected void onDestroy() { super.onDestroy(); //在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview //但是注意:webview调用destory时,webview仍绑定在Activity上//这是由于自定义webview构建时传入了该Activity的context对象//因此需要先从父容器中移除webview,然后再销毁webview: ViewGroup parent = findViewById(R.id.container); parent.removeView(webView); webView.destroy(); }

WebView usage

Adding Network Permissions

 <uses-permission android:name="android.permission.INTERNET" />
  1. Add WebView control to layout file
 <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
  1. Initialize WebView
 WebView webView = (WebView) findViewById(R.id.webview);
  1. Set WebSettings Use the WebSettings class to configure some settings of WebView, such as whether to support JavaScript, whether to allow zooming, etc.
 //声明WebSettings子类WebSettings webSettings = webView.getSettings(); //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript webSettings.setJavaScriptEnabled(true); //支持插件webSettings.setPluginsEnabled(true); //设置自适应屏幕,两者合用webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小//缩放操作webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。 webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件//其他细节操作webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存webSettings.setAllowFileAccess(true); //设置可以访问文件webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
  1. Loading web content WebView can load remote web pages or local HTML resources. Use the loadUrl method to load a web page URL, or use the loadData method to load a piece of HTML data.
 webView.loadUrl("https://www.baidu.com"); // 加载远程网页

Load a local HTML file:

 webView.loadUrl("file:///android_asset/index.html"); // 加载本地HTML文件

Loading HTML data:

 String goods_content="<p>我的第一个段落。</p>"; webView.loadDataWithBaseURL(null, WebUtil.getHtmlData(goods_content), "text/html", "utf-8", null); public static String getHtmlData(String bodyHTML) { String head = "<head>" + "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\"> " + "<style>div,p,img{max-width: 100%; width: 100% !important; height: auto !important;}" + "body {" + "margin-right:8px;" +//限定网页中的文字右边距为15px(可根据实际需要进行行管屏幕适配操作) "margin-left:8px;" +//限定网页中的文字左边距为15px(可根据实际需要进行行管屏幕适配操作) "margin-top:8px;" +//限定网页中的文字上边距为15px(可根据实际需要进行行管屏幕适配操作) "font-size:16px;" +//限定网页中文字的大小为40px,请务必根据各种屏幕分辨率进行适配更改"word-wrap:break-word;" +//允许自动换行(汉字网页应该不需要这一属性,这个用来强制英文单词换行,类似于word/wps中的西文换行) "}" + "p { margin: 0; }" + "</style>" + "</head>"; return "<html>" + head + "<body>" + bodyHTML + "</body><ml>"; }
  1. To handle the general usage of web page loading events, override the shouldOverrideUrlLoading() method so that when a web page is opened, the system browser is not called but displayed in WebView.
 webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } });

Use the WebViewClient or WebChromeClient class to handle some events during the web page loading process, such as the start of page loading, page loading completion, errors, etc.

 WebViewClient webViewClient = new WebViewClient() { /** * shouldOverrideUrlLoading * <p> * 当加载的网页需要重定向的时候就会回调这个函数告知我们应用程序是否需要接管控制网页加载,如果应用程序接管, *并且return true意味着主程序接管网页加载,如果返回false让webview自己处理。 * </p> * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param url * 即将要被加载的url * @return true 当前应用程序要自己处理这个url, 返回false则不处理。 注:"post"请求方式不会调用这个回调函数*/ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (Uri.parse(url).getHost().equals("www.baidu.com")) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); return true; } return false; } /** * onPageStarted 当内核开始加载访问的url时,会通知应用程序,对每个main frame * 这个函数只会被调用一次,页面包含iframe或者framesets 不会另外调用一次onPageStarted, * 当网页内内嵌的frame 发生改变时也不会调用onPageStarted。 * * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param url * 即将要被加载的url * @param favicon * 如果这个favicon已经存储在本地数据库中,则会返回这个网页的favicon,否则返回为null。 */ @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { // TODO Auto-generated method stub super.onPageStarted(view, url, favicon); Log.i(TAG, "onPageStarted:页面开始加载"); } /** * onPageFinished 当内核加载完当前页面时会通知我们的应用程序,这个函数只有在main * frame情况下才会被调用,当调用这个函数之后,渲染的图片不会被更新,如果需要获得新图片的通知可以使用@link * WebView.PictureListener#onNewPicture。 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param url * 即将要被加载的url */ @Override public void onPageFinished(WebView view, String url) { // TODO Auto-generated method stub super.onPageFinished(view, url); Log.i(TAG, "onPageStarted:页面加载结束"); } /** * onLoadResource 通知应用程序WebView即将加载url 制定的资源* * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param url * 即将加载的url 资源*/ @Override public void onLoadResource(WebView view, String url) { // TODO Auto-generated method stub super.onLoadResource(view, url); Log.i(TAG, "onLoadResource:加载资源指定的网址"); } /** * shouldInterceptRequest * 通知应用程序内核即将加载url制定的资源,应用程序可以返回本地的资源提供给内核,若本地处理返回数据,内核不从网络上获取数据。 * * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param url * raw url 制定的资源* @return 返回WebResourceResponse包含数据对象,或者返回null */ @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { // TODO Auto-generated method stub Log.i(TAG, "shouldInterceptRequest"); return super.shouldInterceptRequest(view, url); } /** * onReceivedError * <p> * 当浏览器访问制定的网址发生错误时会通知我们应用程序参数说明: * </p> * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param errorCode * 错误号可以在WebViewClient.ERROR_* 里面找到对应的错误名称。 * @param description * 描述错误的信息* @param failingUrl * 当前访问失败的url,注意并不一定是我们主url */ @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { // TODO Auto-generated method stub super.onReceivedError(view, errorCode, description, failingUrl); view.loadUrl("file:///android_asset/error.html"); Log.i(TAG, "onReceivedError"); } /** * 如果浏览器需要重新发送POST请求,可以通过这个时机来处理。默认是不重新发送数据。 参数说明* * @param view * 接收WebViewClient的webview * @param dontResend * 浏览器不需要重新发送的参数* @param resend * 浏览器需要重新发送的参数*/ @Override public void onFormResubmission(WebView view, Message dontResend, Message resend) { // TODO Auto-generated method stub super.onFormResubmission(view, dontResend, resend); Log.i(TAG, "onFormResubmission"); } /** * doUpdateVisitedHistory * 通知应用程序可以将当前的url存储在数据库中,意味着当前的访问url已经生效并被记录在内核当中。这个函数在网页加载过程中只会被调用一次。 * 注意网页前进后退并不会回调这个函数。 * * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param url * 当前正在访问的url * @param isReload * 如果是true 这个是正在被reload的url */ @Override public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { // TODO Auto-generated method stub super.doUpdateVisitedHistory(view, url, isReload); Log.i(TAG, "doUpdateVisitedHistory"); } /** * 当网页加载资源过程中发现SSL错误会调用此方法。我们应用程序必须做出响应,是取消请求handler.cancel(),还是继续请求handler. * proceed();内核的默认行为是handler.cancel(); * * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param handler * 处理用户请求的对象。 * @param error * SSL错误对象* */ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { // view.loadUrl("file:///android_asset/error.html"); // TODO Auto-generated method stub super.onReceivedSslError(view, handler, error); Log.i(TAG, "onReceivedSslError"); } /** * onReceivedHttpAuthRequest 通知应用程序WebView接收到了一个Http * auth的请求,应用程序可以使用supplied 设置webview的响应请求。默认行为是cancel 本次请求。 * * * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param handler * 用来响应WebView请求的对象* @param host * 请求认证的host * @param realm * 认真请求所在的域*/ @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { // TODO Auto-generated method stub super.onReceivedHttpAuthRequest(view, handler, host, realm); Log.i(TAG, "onReceivedHttpAuthRequest"); } /** * shouldOverrideKeyEvent * 提供应用程序同步一个处理按键事件的机会,菜单快捷键需要被过滤掉。如果返回true,webview不处理该事件,如果返回false, * webview会一直处理这个事件,因此在view 链上没有一个父类可以响应到这个事件。默认行为是return false; * * * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param event * 键盘事件名* @return 如果返回true,应用程序处理该时间,返回false 交由webview处理。 */ @Override public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) { Log.i(TAG, "shouldOverrideKeyEvent"); // TODO Auto-generated method stub return super.shouldOverrideKeyEvent(view, event); } /** * 通知应用程序webview 要被scale。应用程序可以处理改事件,比如调整适配屏幕。 */ @Override public void onScaleChanged(WebView view, float oldScale, float newScale) { // TODO Auto-generated method stub super.onScaleChanged(view, oldScale, newScale); Log.i(TAG, "onScaleChanged"); } /** * onReceivedLoginRequest 通知应用程序有个自动登录的帐号过程* * 参数说明: * * @param view * 请求登陆的webview * @param realm * 账户的域名,用来查找账户。 * @param account * 一个可选的账户,如果是null 需要和本地的账户进行check, 如果是一个可用的账户,则提供登录。 * @param args * 验证制定参数的登录用户*/ @Override public void onReceivedLoginRequest(WebView view, String realm, String account, String args) { // TODO Auto-generated method stub super.onReceivedLoginRequest(view, realm, account, args); Log.i(TAG, "onReceivedLoginRequest"); } });

WebChromeClient assists WebVlew in processing JavaScript dialog boxes, website icons, website tltle, loading progress, etc.

 webView.setWebChromeClient(new WebChromeClient() { /** * onProgressChanged 通知应用程序当前网页加载的进度。 * * 参数说明: * * @param view * 接收WebChromeClient的的webview实例* @param newProgress * webview接受的进度*/ @Override public void onProgressChanged(WebView view, int newProgress) { // TODO Auto-generated method stub super.onProgressChanged(view, newProgress); if (newProgress <= 100) { Log.i(TAG, newProgress + "===onProgressChanged==="); } } /** * 当document 的title变化时,会通知应用程序* * * 参数说明: * * @param view * 接收WebViewClient的webview实例* @param title * document新的title */ @Override public void onReceivedTitle(WebView view, String title) { // TODO Auto-generated method stub super.onReceivedTitle(view, title); Message message = new Message(); message.what = 100; message.obj = title; handler.sendMessage(message); } /** * 当前页面有个新的favicon时候,会回调这个函数。 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param icon * 当前页面的favicon 注:很多时间不会跳转到此回调函数,因为很多网站设置了icon,没有设置favicon, */ @Override public void onReceivedIcon(WebView view, Bitmap icon) { // TODO Auto-generated method stub super.onReceivedIcon(view, icon); Message message = new Message(); message.what = 200; message.obj = icon; handler.sendMessage(message); } /** * 通知应用程序apple-touch-icon的url * * 参数说明: * * @param view * 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new * MyAndroidWebViewClient()),即是这个webview。 * @param url * apple-touch-icon 的服务端地址* @param precomposed * 如果precomposed 是true 则touch-icon是预先创建的* * Tips * * 如果应用程序需要这个icon的话, 可以通过这个url获取得到icon。 */ @Override public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed) { // TODO Auto-generated method stub super.onReceivedTouchIconUrl(view, url, precomposed); Log.i(TAG, "====onReceivedTouchIconUrl===="); } /** * webview请求得到focus,发生这个主要是当前webview不是前台状态,是后台webview。 */ @Override public void onRequestFocus(WebView view) { // TODO Auto-generated method stub super.onRequestFocus(view); Log.i(TAG, "====onRequestFocus===="); } /** * 覆盖默认的window.alert展示界面, */ @Override public boolean onJsAlert(final WebView view, String url, String message, JsResult result) { final AlertDialog.Builder builder = new AlertDialog.Builder( view.getContext()); builder.setTitle("对话框").setMessage(message) .setPositiveButton("确定", null); builder.setOnKeyListener(new OnKeyListener() { public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { Log.v("onJsAlert", "keyCode==" + keyCode + "event=" + event); return true; } }); // 禁止响应按back键的事件builder.setCancelable(false); AlertDialog dialog = builder.create(); dialog.show(); result.confirm();// 因为没有绑定事件,需要强行confirm,否则页面会变黑显示不了内容。 return true; // return super.onJsAlert(view, url, message, result); } /** * 覆盖默认的window.confirm展示界面, */ @Override public boolean onJsConfirm(final WebView view, String url, String message, final JsResult result) { final AlertDialog.Builder builder = new AlertDialog.Builder( view.getContext()); builder.setTitle("对话框").setMessage(message) .setPositiveButton("确定", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { result.confirm(); } }).setNeutralButton("取消", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { result.cancel(); } }); builder.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { result.cancel(); } }); // 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { Log.v("onJsConfirm", "keyCode==" + keyCode + "event=" + event); return true; } }); // 禁止响应按back键的事件// builder.setCancelable(false); AlertDialog dialog = builder.create(); dialog.show(); return true; } /** * 覆盖默认的window.prompt展示界面, */ @Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) { final AlertDialog.Builder builder = new AlertDialog.Builder( view.getContext()); builder.setTitle("对话框").setMessage(message); final EditText et = new EditText(view.getContext()); et.setSingleLine(); et.setText(defaultValue); builder.setView(et).setPositiveButton("确定", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { result.confirm(et.getText().toString()); } }).setNeutralButton("取消", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { result.cancel(); } }); // 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new OnKeyListener() { public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { Log.v("onJsPrompt", "keyCode==" + keyCode + "event=" + event); return true; } }); // 禁止响应按back键的事件// builder.setCancelable(false); AlertDialog dialog = builder.create(); dialog.show(); return true; // return super.onJsPrompt(view, url, message, defaultValue, // result); } });
  1. Handling the interaction between JavaScript and Android code If the web page contains JavaScript and needs to interact with Android code, you can use the addJavascriptInterface method of WebView to achieve it. Define an object in the Android code and call the method of this object in JavaScript.

Write an HTML file and put it in the assets file:

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div> function say(value){</br>  callJS(value);</br> } </div> </body> <script> function callJS(value){ alert(value); return value; } </script> </html>

Android calls js:

 public class MainActivity extends AppCompatActivity { private WebView webview; private TextView tvAndroid; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webview = (WebView) findViewById(R.id.webview); tvAndroid = (TextView) findViewById(R.id.tv_android); tvAndroid.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Android调用js方法//Android 4.4以下使用loadUrl,Android 4.4以上evaluateJavascript if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { webview.loadUrl("javascript:callJS('aaa')"); } else { webview.evaluateJavascript("javascript:callJS('aaa')", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { //此处为js 返回的结果Toast.makeText(MainActivity.this,value,Toast.LENGTH_SHORT).show(); } }); } } }); initWebView(); } public void initWebView() { //启用JS脚本webview.getSettings().setJavaScriptEnabled(true); // 设置允许JS弹窗webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); //加载网页webview.loadUrl("file:///android_asset/index.html"); // 由于设置了弹窗检验调用结果,所以需要支持js对话框// webview只是载体,内容的渲染需要使用webviewChromClient类去实现// 通过设置WebChromeClient对象处理JavaScript的对话框//设置响应js 的Alert()函数webview.setWebChromeClient(new WebChromeClient(){ @Override public boolean onJsAlert(WebView view, String url, String message, JsResult jsResult) { new AlertDialog.Builder(view.getContext()).setMessage(message).setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { jsResult.confirm(); } }).setCancelable(false).create().show(); return true; } }); //覆盖WebView默认使用第三方或系统默认浏览器打开网页的行为,使网页用WebView打开webview.setWebViewClient(new WebViewClient() { //override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { handler.proceed("admin", "sunlight"); int d = Log.d("MyWebViewClient", "onReceivedHttpAuthRequest"); } @Override public boolean shouldOverrideUrlLoading(WebView view, String uri) { // TODO Auto-generated method stub //返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器view.loadUrl(uri); return true; } }); } }

"Note" The js code call must be called after the onPageFinished() callback, otherwise it will not be called.

js calls Android method: Object mapping through WebView's addJavascriptInterface()

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <button style="width:100%;height:50px; margin-top: 100px;" onclick="aa.showToast('哈哈哈')">js调用Android方法</button> </body> </html>
 public class MainActivity2 extends AppCompatActivity { private WebView webview; private TextView tvAndroid; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); webview = (WebView) findViewById(R.id.webview); tvAndroid = (TextView) findViewById(R.id.tv_android); tvAndroid.setText("//继承自Object类,别名是aa,即在html可以直接用aa.showToast(\"哈哈哈\")来调用android方法\n" + "public class MyObject extends Object {\n" + " @JavascriptInterface\n" + " public void showToast(String name){\n" + " Toast.makeText(MainActivity2.this, \"您好!\"+name, Toast.LENGTH_SHORT).show();\n" + " }\n" + "}"); initWebView(); } public void initWebView() { // 设置与Js交互的权限webview.getSettings().setJavaScriptEnabled(true); //将java对象暴露给JavaScript脚本//参数1:java对象,里面定义了java方法//参数2:Java对象在js里的对象名,可以看作第一个参数的别名,可以随便取,即在html可以直接用aa.showToast("哈哈哈")来调用android方法webview.addJavascriptInterface(new MyObject(), "aa");//AndroidtoJS类对象映射到js的test对象//加载网页webview.loadUrl("file:///android_asset/index2.html"); } //继承自Object类,别名是aa,即在html可以直接用aa.showToast("哈哈哈")来调用android方法public class MyObject extends Object { // 定义JS需要调用的方法// 被JS调用的方法必须加入@JavascriptInterface注解@JavascriptInterface public void showToast(String name){ Toast.makeText(MainActivity2.this, "您好!"+name, Toast.LENGTH_SHORT).show(); } } }
  1. Page Back
 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) { webView.goBack(); return true; } return super.onKeyDown(keyCode, event); }
  1. Cache Configuration
 WebSettings webSettings = webView.getSettings(); //优先使用缓存webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //只在缓存中读取webSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY); /不使用缓存webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
  1. Clear the cache
 //清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序. webview.clearCache(true); //清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录. webview.clearHistory (); //这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据。 webview.clearFormData ();

Notice

There are some common problems in the use of WebView "Performance Issues" When WebView loads H5 pages, the page loading speed may be slow due to the complex JS parsing process, the large number of JS code files involved in the front-end page, and the differences in mobile phone hardware performance caused by the fragmentation of Android models. Each time an H5 page is loaded, more network requests will be generated, including the main URL request of HTML and the external JS, CSS, font files, image files, etc. referenced by HTML, which will consume a certain amount of traffic and time.

"Memory management problem" WebView is attached to Activity, and the life cycle of Activity may be inconsistent with the life cycle of the thread started by WebView, which may cause WebView to always hold a reference to Activity and cannot release it, thus causing memory leaks. Improper use of WebView may cause the application to occupy a large amount of memory during operation, or even cause the application to crash.

[Security Vulnerabilities] There may be some security vulnerabilities in WebView, such as remote code execution vulnerabilities, password plaintext storage vulnerabilities, and lax domain control vulnerabilities, etc. Attackers may use WebView to execute methods of arbitrary Java objects, steal user information, or even control user devices.

[Compatibility issues] Different versions of Android systems or different brands of mobile phones may have WebView compatibility issues. For example, some models may not support WebGL, resulting in some web page content not being displayed properly. WebView may also have compatibility issues when loading web pages in certain formats or performing certain operations.

<<:  Master the powerful functions of ClipboardManager in Android development and efficiently manage clipboard data

>>:  Exploring the Android system: dumpsys command to obtain detailed information about system services

Recommend

The TikTok case becomes a real practice!

These two days, I suddenly found that many classm...

Summer is coming, is it reliable to lose weight by sleeping?

Summer is coming, and losing weight is becoming a...

Want to find someone with the same birthday as you? It’s not that difficult!

When you hear someone has the same birthday as yo...

Chen Qingzhu's Physiognomy Episode 15

Chen Qingzhu's Physiognomy 15 episodes resour...

“Meituan Takeout” product analysis report!

Take-out has become a must-have for urbanites, sa...

Optimize 200 series AMD releases the latest 15.7 WHQL driver

AMD has released the latest graphics card catalys...

A tearful suggestion on advertising purchased with a budget of 1 million

Summary of advertising placement on 7 major chann...

Unscrupulous merchants are crying! iOS 15.2 can check the authenticity of parts

[[441793]] The official version of iOS 15.2 has b...

The evolution of super APP content

[[248684]] Reviewing the three major super apps u...

Compose-Multiplatform Practice on Android and iOS

01 Introduction We have previously discussed KMM,...

Complete workplace PPT, one course to solve 95% of workplace problems

Course objectives: With Microsoft Office PowerPoi...

How to effectively promote the product in the early stage?

"Successfully executing a plan that makes no...

10 Practical but Paranoid Java Programming Techniques

[[147453]] After you've been coding for a whi...