I think everyone knows this problem. It exists on all versions of android and how to get rid of it, I have not yet found. When you open the web-based activation, the app eats an additional 8 megabytes (maybe more). When the window is closed (and, accordingly, all kinds of clear, destroy, = null are called), the wrinkle is not released. Moreover, when entering activation again, more and more memory is leaking. The method of rendering the creation of a webview inside code, and not markup does not help. Tell me how to fix it?


public class CarWebViewActivity extends Activity { @Override public void onCreate(Bundle saved) { super.onCreate(saved); setContentView(R.layout.web_layout); Bundle extras = getIntent().getExtras(); final String href = extras.getString("href"); ((TextView) findViewById(R.id.header_title)).setText(extras.getString("title")); findViewById(R.id.web_layout_top_bar_button_reload).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (href != null) webView.loadUrl(href); } }); LinearLayout root = (LinearLayout) findViewById(R.id.web_layout_root); webView = new WebView(getApplicationContext()); root.addView(webView); webView.setWebViewClient(new HelloWebViewClient()); if (href != null) webView.loadUrl(href); webView.setWebChromeClient(new MyWebChromeClient()); webView.getSettings().setBlockNetworkImage(false); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setLoadsImagesAutomatically(true); } WebView webView; private final class HelloWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); return true; } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Log.e("Ошибка страницы", "ошибка страницы"); AlertDialog alertDialog = new AlertDialog.Builder(CarWebViewActivity.this) .setMessage("Для отображения страницы необходимо интернет соединение") .setPositiveButton("Вернуться", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { finish(); } }).show(); super.onReceivedError(view, errorCode, description, failingUrl); } } public final class MyWebChromeClient extends WebChromeClient { public void onProgressChanged(WebView view, int progress) { try { findViewById(R.id.progressinheader).setVisibility(View.VISIBLE); findViewById(R.id.web_layout_top_bar_button_reload).setVisibility(View.GONE); if (progress == 100) { findViewById(R.id.progressinheader).setVisibility(View.GONE); findViewById(R.id.web_layout_top_bar_button_reload).setVisibility(View.GONE); } } catch (Exception e) { } } } @Override public void onDestroy() { super.onDestroy(); webView.stopLoading(); webView.clearCache(true); webView.clearView(); webView.freeMemory(); webView.destroy(); webView = null; findViewById(R.id.progressinheader).setVisibility(View.GONE); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.about_item: Intent intent = new Intent(getApplicationContext(), AboutActivity.class); startActivity(intent); break; default: return super.onOptionsItemSelected(item); } return true; } } 
  • well, nobody really knows? - LackOfKnowledge
  • So doesn't this memory go away later? This is an android, it will not release the memory, while there is free, and he does not need more. - Chad
  • one
    so far I can advise this to be set on the stack =) - Gorets
  • one
    You also probably need to see how it is done in phoneGap - they obviously use the right web view. - Chad
  • one
    in C # for example, there is [GC.Collect();](http://msdn.microsoft.com/en-us/library/xe0c2357.aspx) sure there is something similar in java - Specter

3 answers 3

Here I found on call Garbudzh team in Java:

If you assign null to the links and call gc (), then it will work only when there is time in the stream to execute gc (). If the stream is busy and there is not enough memory because of an obj object that is not needed, you can try

 obj = null; System.gc(); Thread.yield(); try { Thread.sleep(20); } catch(Exception e){ } 
  • Although I do not like it, but the attempt is not torture. I will test - I will unsubscribe - LackOfKnowledge
  • Great try, what's the point? get System.gc ();, and then pause the program? what for? Do you think the garbage collector will work at this time? - Gorets
  • manual gc is a bad practice. If the program is not in the background, then the system will be the last to nail it. But if it is in the background and not a service - so it is on time - this is the ideology of the android. - KoVadim
  • @Gorets - a pause in order for the collector to try to work out - the system calls it after the request "System.gc ()" only if there is time for that. If the thread is idle (sleep), then you can call. - Chad
  • 2
    And he is not obliged to be called. If the code will rely on a call to the GC - this is a bad code. - KoVadim
 void clearCache(Context context) { clearCacheFolder(context.getCacheFolder()); } void clearCacheFolder(final File dir) { if (dir!= null && dir.isDirectory()) { try { for (File child:dir.listFiles()) { //рекурсивно чистим сначала каталоги if (child.isDirectory()) clearCacheFolder(child); else //потом собственно файлы child.delete(); } } catch(Exception e) { Log.e(TAG, "Failed to clean the cache error message="+e.getMessage()); } } } 

    The standard cause of a memory leak is an attempt to save references to the Activity/Context in its classes. Read a good article on this topic.

    • one
      Please note that the question is not a newcomer to android. I did not expect such a banal response - LackOfKnowledge
    • @alvin: Well, of course the pros from afar can be seen by calling gc () in the code. Exercise further :) - Barmaley 5:02 pm