当活动正在执行时,指向Activity的Android弱引用变为null

6
我遇到了一个NullPointerException, 我不明白为什么会出现这种情况。mainActivityWeakReference.get()返回null。 我猜测这是因为当Activity被重新创建时,引用变量被设置为空,一旦类被加载,引用才会在onCreate方法被调用后更新。但我不理解的是,我正在执行活动中的指令,而该引用指向该活动,但引用却为空。 活动是否可以共存一小段时间?我该如何处理这种情况呢? 对我来说,似乎简单的空检查并不能解决问题。也许我应该调用finish()方法。
public class MainActivity extends android.support.v7.app.AppCompatActivity {

  private WeakReference<AppCompatActivity> mainActivityWeakReference = null;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
         mainActivityWeakReference = new WeakReference<AppCompatActivity>(this);
  }

   public void handleAction(UserAction userAction) {
        switch (userAction) {
           case UPDATE_UI:
                << ERROR HERE
                mainActivityWeakReference.get().getSupportFragmentManager().executePendingTransactions();
                break;
       }
    }

我的堆栈跟踪:

java.lang.NullPointerException: Attempt to read from field 'android.os.Handler android.support.v4.a.m.a' on a null object reference
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1476)
    at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:490)
    at za.co.entersekt.nedbank.MainActivity.handleAction(MainActivity.java:297)

补充更多详细信息:

public abstract class FragmentManager {
....

public boolean execPendingActions() {
        if (mExecutingActions) {
            throw new IllegalStateException("Recursive entry to executePendingTransactions");
        }

        if (Looper.myLooper() != mActivity.mHandler.getLooper()) {<<FragmentManager.java:1476
            throw new IllegalStateException("Must be called from main thread of process");
        }

1
所有这些代码都在一个Activity中吗?为什么要持有对this的弱引用?调用this.getSupportFragmentManager()太容易了吗? - Eugen Pechanec
同时,mainActivityWeakReference.get() 似乎返回了 null。而且 << ERROR HERE 不是真的...它更深层次...可能是因为 Activity 处于错误状态... - Selvin
https://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/app/FragmentManager.java#L1588 ... mHost为空 - 正如我之前所写,因为Activity处于某种不可用状态。 - Selvin
我已经添加了更多细节:(FragmentManager.java:1476)的反编译代码。 - Wayne
这可能是因为我没有在主线程上执行:mainActivityWeakReference.get().getSupportFragmentManager().executePendingTransactions();你有什么想法? - Wayne
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3
那是因为按定义,弱引用是一种不会防止垃圾回收器回收所引用对象的引用
如果你需要一个Activity的实例,可以尝试使用 getActivity()getContext()

为什么我会收到空指针异常?执行语句时,Activity肯定没有被垃圾回收。 - Wayne
1
是的,这个活动不为空,因为屏幕在那里,但是弱引用可能会被垃圾回收。尝试使用 getActivity() 并检查它是否有效。 - Mightian
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Wayne
可能是真的,因为我从未尝试过,因为这不是一个真实的场景,我希望它能够与getActivity一起工作。 - Mightian

0
我的解决方案是通过钩子方法获取活动:
public class MainFragment extends Fragment implements....
//....

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    activityWeakReference = new WeakReference<>((AppCompatActivity) activity);
}

是的,活动可能因多种原因而重新创建,在那时弱引用变为空,不持有强引用,因此可以进行垃圾回收。

如果它持有强引用,整个活动将不符合垃圾回收的条件,这是一种严重的内存泄漏,会将内存保留得比应该更长时间。

活动可能因多种原因而重新创建,其中一些原因是:方向改变、语言更改甚至是因为某些内存限制而由Android决定执行此操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,