Using application context instead of activity context

This question is an extension of this question that I posted yesterday. I found a possible memory leak and figured it out correctly. One of the memory leaks caused by the non-stationary inner class is the more accurate non-static Handler .

But today I ran into a new memory leak problem. I read this post , the essence of which is based on Context , the context of an activity or application. enter image description here

This is the pie chart I got from Eclipse Memory Analyzer

I saw that changes in the Remainder this pie chart occur after fixing problems with the Handler , the Remainder increased from 10.6 MB.

But in the context of the problem, Problem Suspect 2 gives me a hint where to look

 35 instances of "android.widget.FrameLayout", loaded by "<system class loader>" occupy 39 218 464 (39,94%) bytes. Biggest instances: •android.widget.FrameLayout @ 0x425aa258 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x425d9b20 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x42609258 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x4260a248 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x42925960 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x429808e0 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x429a4350 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x429d9b20 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x429e5710 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x42a28c98 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x42a51b80 - 3 266 728 (3,33%) bytes. •android.widget.FrameLayout @ 0x46a8caf0 - 3 266 728 (3,33%) bytes. 

He tells me that a memory leak occurs where I use FrameLayout . The only place I use FrameLayout is in my Splash Screen .

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.splash); utils = new AppUtils(getApplicationContext()); pd = (ProgressBar) findViewById(R.id.pd); progress = (TextView) findViewById(R.id.progress); version = (TextView)findViewById(R.id.version); prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); SharedPreferences.Editor prefEditor = prefs.edit(); prefEditor.putString("firstpw", "first"); prefEditor.commit(); folder = new CreateApplicationFolder(getApplicationContext(), true); boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); if (!isSDPresent) { ErrorDialog dialog = new ErrorDialog(getApplicationContext(), getResources().getString(R.string.sdCardTitle), getResources().getString(R.string.sdCardContent), getResources().getString(R.string.ok), 2); Log.i("SDCARD: ", "Is Not Present"); dialog.canCancelDialog(false); } else { Log.i("SDCARD: ", "Is Present"); version.setText("Version: " + utils.getAppVersion()); try { new ReadConfig(Splash.this, pd, progress).execute(""); } catch (ParserConfigurationException e) { Log.e("Parser: ", e.getMessage()); } catch (SAXException e) { Log.e("Sax: ", e.getMessage()); } catch (IOException e) { Log.e("IO: ", e.getMessage()); } } } 

I suspect a memory leak occurs when I submit an Activity context to AsyncTask ReadConfig , for example:

 try { new ReadConfig(Splash.this, pd, progress).execute(""); } catch (ParserConfigurationException e) { Log.e("Parser: ", e.getMessage()); } catch (SAXException e) { Log.e("Sax: ", e.getMessage()); } catch (IOException e) { Log.e("IO: ", e.getMessage()); } 

And in the ReadConfig class, I also use this context to start a new Activity in the onPostExecute method, which will save this context.

 protected void onPostExecute(String result) { if (result.equals("noConfig")) { Toast.makeText(context, context.getResources().getString(R.string.configNotFound), Toast.LENGTH_LONG).show(); Intent mainIntent = new Intent(context, MainClass.class); context.startActivity(mainIntent); } else if(result.equals("pathnotFound")) { new ErrorDialog(context, context.getResources().getString(R.string.noBTFolderTitle), context.getResources().getString(R.string.noBtFolderContent), context.getResources().getString(R.string.exit), 2); } else { Intent mainIntent = new Intent(context, MainClass.class); context.startActivity(mainIntent); } } 

I need context to trigger this new action, retrieve rows from resources, etc. Is there any possible way to do this differently to avoid memory leak? Thanks for reading this great post and just add a comment if you need more code or something else.

Thanks in advance.

+4
source share
1 answer

You should probably try to use the application context and not the activity context where possible (this is not always possible).

To access the application context everywhere, you can define your own application class

 class MyApp extends Application { private static MyApp mInstance; @Override public void onCreate() { mInstance = this; } public static Context context() { return mInstance.getApplicationContext(); } } 

Then you declare this class in your manifest

 <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="com.myapp.MyAppClass"> 

and use MyApp.context () where applicable

+3
source

Source: https://habr.com/ru/post/1447685/


All Articles