使用Application上下文而不是Activity Context

时间:2012-11-22 09:06:36

标签: android ddms

这个问题是我昨天发布的question的扩展。我发现了一个可能的内存泄漏,并以正确的方式解决了这个问题。其中一个内存泄漏是由非静态内部类引起的,更精确的是非静态Handler

但我今天面临新的内存泄漏问题。我已经阅读了这个post,其实质是基于Context,活动或应用程序上下文。 enter image description here

这是我从Eclipse Memory Analyzer

获得的饼图

我已经看到此饼图的Remainder发生了变化,在修复Handler问题后,剩余量增加了10.6 MB。

但是对于上下文问题,Problem Suspect 2给了我一个提示在哪里看

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. 

它告诉我内存泄漏发生在我使用FrameLayout的地方。我使用FrameLayout的唯一地方是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());
        }
    }
}

我怀疑当我将Activity上下文发送到AsyncTask ReadConfig时会发生内存泄漏,如下所示:

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());
        }

在ReadConfig类中,我也使用此上下文在Activity方法中启动新的onPostExecute,这将使此上下文保持活动状态。

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);
        }
    }

我需要上下文来启动这个新的Activity,从资源中获取字符串等等。有什么方法可以做到这一点,以避免内存泄漏?感谢阅读这篇重要文章,如果您需要更多代码或其他任何内容,请添加评论。

提前致谢。

1 个答案:

答案 0 :(得分:3)

您可能应尽量使用应用程序上下文而不是活动上下文(并非总是可行)。

要从任何地方访问您的应用程序上下文,您可以定义自己的应用程序类

class MyApp extends Application
{
private static MyApp mInstance;

@Override
public void onCreate()
{
   mInstance = this;
}

public static Context context()
{
   return mInstance.getApplicationContext();
}

}

然后在清单

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

并在适用的地方使用MyApp.context()