It’s not easy for WebView to say I love you

It’s not easy for WebView to say I love you

[[189802]]

Why use WebView?

With the continuous development of app business, it is unrealistic to rely solely on native code to pile up functions. After all, the development time will increase, and both iOS and Android need to be developed at the same time. Moreover, if the UI is changed a little bit, a package needs to be moved (although Android can now perform hot updates, hot updates are not 100% effective. Anyone who has understood the principle will know it). In the end, we will choose to use native nested H5 for development. In this way, we can change the UI at any time and expand functions arbitrarily. Then, we will use Android's WebView, the control that makes us both sad and happy.

Nowadays, mobile phones are highly customized, and the native code of the system will be modified and added to a certain extent. The effects presented by WebView of different mobile phones are also different, which can be said to be colorful, so I understand the pain of Android developers. Next, I will explain my experience of using WebView in the project in detail. If you don't like it, please don't criticize me.

use

At the beginning, I believe everyone added the WebView control directly to the layout file. Of course, I did the same at the beginning, just for simplicity, and I didn’t know what problems would arise.

  1. <WebView
  2.  
  3. android:id= "@+id/web_view"      
  4.  
  5. android:layout_width= "match_parent"      
  6.  
  7. android:layout_height= "match_parent" />

Just add a WebView like this, and you will find that there is no problem, it can be displayed as usual, and everything is normal. When you repeatedly open the page with WebView, you will find that the memory of the application will continue to increase, and it will not drop after being destroyed, and it will not drop even if you click GC. This is a memory leak. At this time, you will find that it is incorrect to use WebView in this way, so what is the best way to use it?

That is to add it dynamically in the code.

First, declare a parent layout in the layout file

  1. <LinearLayout
  2.  
  3. android:id= "@+id/web_view"  
  4.  
  5. android:layout_width= "match_parent"  
  6.  
  7. android:layout_height= "wrap_content"  
  8.  
  9. android:orientation= "horizontal"  
  10.  
  11. android:scrollbars= "none" />

Then in the code, add WebView as its child View

  1. WebView webView = new WebView(context);
  2.  
  3. webViewLayout.addView(webView);

Many people on the Internet say that this context should use the application. I think it is wrong. What if your WebView needs to pop up a dialog? There are other unpredictable problems. It is best to use the Context of the current activity.

The above is about how to add WebView for use, and then what properties of it do we need to use in development?

  1. webView.loadUrl( "www.baidu.com" ); //WebView loads the webpage using loadUrl
  2.  
  3. WebSettings webSettings = webView.getSettings(); //Get WebView settings
  4.  
  5. webSettings.setUseWideViewPort( true ); // Set this property to scale at any ratio
  6.  
  7. webSettings.setLoadWithOverviewMode( true );//Adaptation
  8.  
  9. webSettings.setJavaScriptEnabled( true ); //Support js
  10.  
  11. webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); //Set cache mode
  12.  
  13. webSettings.setDomStorageEnabled( true ); // Enable DOM storage API function
  14.  
  15. webSettings.setDatabaseEnabled( true ); // Enable database storage API function
  16.  
  17. webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); //HTTPS, note that this is called above LOLLIPOP
  18.  
  19. webSettings.setAppCacheEnabled( true ); // Enable Application Caches
  20.  
  21. webSettings.setBlockNetworkImage( true ); //Turn off loading network images. Set this to true at the beginning of loading , and set it to false when the web page is finished loading.  

The above are the most basic settings for using WebView. I believe that the above settings will be performed during the development process.

  1. webView.setWebChromeClient(new WebChromeClient() {
  2.  
  3. @Override
  4.  
  5. public void onProgressChanged(WebView view , int newProgress) {
  6.  
  7. //Loading progress
  8.  
  9. }
  10.  
  11. @Override
  12.  
  13. public void onReceivedTitle(WebView view , String title) {
  14.  
  15. //Get the title of the WebView
  16.  
  17. }
  18.  
  19. @Override
  20.  
  21. public boolean onJsAlert(WebView view , String url, String message, final JsResult result) {
  22.  
  23. return super.onJsAlert( view , url, message, result);
  24.  
  25. //Js pop-up box
  26.  
  27. }
  28.  
  29. @Override
  30.  
  31. public boolean onJsConfirm(WebView view , String url, String message, final JsResult result) {
  32.  
  33. AlertDialog.Builder b = new AlertDialog.Builder(IllegalQueryActivity.this);
  34.  
  35. b.setTitle( "Delete" );
  36.  
  37. b.setMessage(message);
  38.  
  39. b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  40.  
  41. @Override
  42.  
  43. public void onClick(DialogInterface dialog, int which) {
  44.  
  45. result.confirm();
  46.  
  47. }
  48.  
  49. });
  50.  
  51. b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
  52.  
  53. @Override
  54.  
  55. public void onClick(DialogInterface dialog, int which) {
  56.  
  57. result.cancel();
  58.  
  59. }
  60.  
  61. });
  62.  
  63. b.create ().show();
  64.  
  65. return   true ;
  66.  
  67. }
  68.  
  69. });
  70.  
  71. webView.setWebViewClient(new WebViewClient() {
  72.  
  73. @Override
  74.  
  75. public boolean shouldOverrideUrlLoading(WebView view , String url) {
  76.  
  77. //You need to set the web page to be displayed in the current WebView so that it will not jump to the default browser for display
  78.  
  79. return   true ;
  80.  
  81. }
  82.  
  83. @Override
  84.  
  85. public void onReceivedError(WebView view , WebResourceRequest request, WebResourceError error) {
  86.  
  87. super.onReceivedError( view , request, error);
  88.  
  89. //Loading error
  90.  
  91. }
  92.  
  93. @Override
  94.  
  95. public void onPageFinished(WebView view , String url) {
  96.  
  97. super.onPageFinished( view , url);
  98.  
  99. //Loading completed
  100.  
  101. }
  102.  
  103. });
  104.  
  105. webView.setDownloadListener(new DownLoadListener()); //Download listener
  106.  
  107. private class DownLoadListener implements DownloadListener {
  108.  
  109. @Override
  110.  
  111. public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
  112.  
  113. }
  114.  
  115. }

Then there is the interaction between WebView and JS

  1. webView.addJavascriptInterface(new WebAppInterface(this), "WebJs" );
  2.  
  3. public class WebAppInterface {
  4.  
  5. Context mContext;
  6.  
  7. public WebAppInterface(Context c) {
  8.  
  9. mContext = c;
  10.  
  11. }
  12.  
  13. @JavascriptInterface
  14.  
  15. public void method() {
  16.  
  17. }
  18.  
  19. }
  20.  
  21. webView.loadUrl( "javascript:jsMethod()" ); //This is the simplest way to call JS in WebView

When the activity executes the life cycle, it is important to note that WebView needs to be destroyed during onDestroy, otherwise memory leaks will occur.

  1. @Overrideprotected void onPause() {
  2.  
  3. super.onPause();
  4.  
  5. if (webView != null ) {
  6.  
  7. webView.onPause();
  8.  
  9. }
  10.  
  11. }
  12.  
  13. @Override
  14.  
  15. protected void onResume() {
  16.  
  17. super.onResume();
  18.  
  19. if (webView != null ) {
  20.  
  21. webView.onResume();
  22.  
  23. }
  24.  
  25. }
  26.  
  27. @Override
  28.  
  29. protected void onDestroy() {
  30.  
  31. if (webView != null ) {
  32.  
  33. webView.clearCache( true ); // Clear the cache
  34.  
  35. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
  36.  
  37. if (webViewLayout != null ) {
  38.  
  39. webViewLayout.removeView(webView);
  40.  
  41. }
  42.  
  43. webView.removeAllViews();
  44.  
  45. webView.destroy();
  46.  
  47. } else {
  48.  
  49. webView.removeAllViews();
  50.  
  51. webView.destroy();
  52.  
  53. if (webViewLayout != null ) {
  54.  
  55. webViewLayout.removeView(webView);
  56.  
  57. }
  58.  
  59. }
  60.  
  61. webView = null ;
  62.  
  63. }
  64.  
  65. }

You can see that the system version is judged in the onDestroy method above. That's because I tested it in different versions. If the WebView version is lower than 5.0, if the WebView is removed from the parent first, the WebView will not be destroyed, which will cause memory leaks. You can try it yourself to see if this statement is correct.

Another problem we are facing now is that when WebView is nested in ScrollView, some models will have screen flashing problems, which will not happen when using WebView alone. After turning off hardware acceleration, the user experience is not good. Therefore, we have not thought of a better solution yet, so it is recommended not to nest controls such as WebView in ScrollView.

<<:  Things about memory optimization in Android - a record of image optimization

>>:  Android full set of animation usage tips

Recommend

The cargo spacecraft does not carry people, is it a manned spacecraft?

Cargo spacecraft are the backbone of manned space...

Stop it! If you love picking your nose, be careful not to damage your brain!

Source: Dr. Curious The cover image of this artic...

What is the viral user growth model? How to build a user growth model?

The concept of growth hacking is very popular now...

Goodbye! iPhone jailbreaking is dead

I believe many friends still remember "PP As...

Four key words for new marketing: scenarios, IP, communities, and communication

What is New Marketing? There are four key words: ...