我的活动是否被泄露 - 是ActionBar正在做什么?

时间:2013-09-14 20:44:15

标签: java android memory-leaks

我有一个名为PhotoSelectorActivity的Activity。它继承自BaseActivity,如下所示:

public class BaseActivity
extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d(this.getClass().getSimpleName(),
        "onCreate("+Integer.toHexString(System.identityHashCode(this))+")");
}

@Override
protected void onDestroy() {
    super.onDestroy();
    getSupportActionBar().setCustomView(null);
    Log.d(this.getClass().getSimpleName(),
        "onDestroy("+Integer.toHexString(System.identityHashCode(this))+")");
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            return onNavigateUp(item);
        case R.id.menu_item_settings:
            startActivity(new Intent(this, PreferencesActivity.class));
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
protected ActionBar setupActionBar(boolean enableBackButton) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        getSupportActionBar().setDisplayHomeAsUpEnabled(enableBackButton);
    }
    ActionBar actionBar = getSupportActionBar();
    actionBar.setCustomView(R.layout.action_bar);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(true);
    return null;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}

此BaseActivity的目的是为我的每个活动提供相同的菜单和操作栏。您会注意到getSupportActionBar().setCustomView(null)方法中的onDestroy(),即可以尝试解决我可能遇到的问题。

当我收到方向更改事件时,我注意到在DDMS中我最终得到了2个我的活动实例。其中一个可能正在泄漏,但我不确定。这是DDMS的屏幕截图:

DDMS screenshot of offending extra activity

所以顶部的对象是有问题的Activity:PhotoSelectorActivity。此处显示的实例是前一个实例(已在其上调用onDestroy())。然而,即使在通过DDMS强制GC之后它仍然存在于内存中。

另一点信息是,这似乎只在使用对话框后发生。也就是说,当Activity最初显示时,在用户执行和操作之前,我可以背靠背方向更改,而不会超过上面的#1活动。在我使用下面的对话框后,我似乎在内存中获得了额外的Activity :

public class PhotoSourceDialog
extends DialogFragment
implements DialogInterface.OnClickListener {

public static interface PhotoSourceDialogListener {
    void onPhotoSourceSelected(String result);
}

private PhotoSourceDialogListener listener;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    if (!PhotoSourceDialogListener.class.isInstance(activity)) {
        throw new IllegalStateException(
            "Activity must implement PhotoSourceDialogListener");
    }
    listener = PhotoSourceDialogListener.class.cast(activity);
}

@Override
public void onDetach() {
    super.onDetach();
    listener = null;
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new AlertDialog.Builder(getActivity())
        .setTitle(R.string.photo_source)
        .setItems(R.array.photo_sources, this).create();
}

@Override
public void onClick(DialogInterface dialog, int which) {
    String choice = getResources().getStringArray(
        R.array.photo_sources)[which];
    if (listener!=null) {
        listener.onPhotoSourceSelected(choice);
    }
}

}

并调用它我在我的活动中这样做:

PhotoSourceDialog dialog = new PhotoSourceDialog();
dialog.show(getSupportFragmentManager(), PhotoSourceDialog.class.getName());

所以我的问题是:我应该担心吗?这只是一些闲逛但最终会成为GCd的东西吗?我认为如果有泄漏,它会增长到高于2.

1 个答案:

答案 0 :(得分:0)

我正在结束这个问题。谷歌的某位回复了以下内容:

  

好的,在那种情况下,它不是自标准以来的AppCompat错误   操作栏实现用于ICS +。

     

看看那个MAT截图,框架的ActionMenuItemView是   从正在最终确定的剪贴板事件中引用,   因此即将成为GC'd。 LayoutInflater 可能是   Activity保留自己的LayoutInflater(getLayoutInflater())。