实用工具类的静态成员(null)生命周期

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实用工具类的静态成员(null)生命周期相关的知识,希望对你有一定的参考价值。

我有一个具有常量和静态方法的实用程序类。此外,它有一个静态字段。

public class MyUtil implements IMyUtil {
   public static String IS_DEBUG = false;
   ...
   private static MyEnumType mMyEnum;

   ...
   // static getter setter methods for mMyEnum
}

我有两个片段(FragmentA和FragmentB为了简单起见)。 FragmentA设置mMyEnum值,然后将其与getter方法一起使用。当用户按下按钮时,我显示FragmentB。在FragmentB的onActiviyCreated()方法中,我得到mMyEnum值。

在我的测试设备上一切正常。但在Google Play控制台中,我在此行看到了一堆NullPointerException错误:

String testString = MyUtil.getMyEnum().getSomeStringValue();

我无法弄清楚为什么myEnum在该行上为null以及为什么我无法重现它。 MyUtil显然不能为null,getSomeStringValue()可以为null,但它不会抛出NullPointerException,所以唯一的myEnum可以为null。但为什么?如果它可以为null我怎么能重现它?

谢谢。

更新#1:播放显示各种设备(三星A3,S6,S7,S8,LG X,G3,华为P9等)和API版本(5.0 - > 7.1)。完整堆栈跟踪是:

java.lang.RuntimeException: 
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2984)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3045)
  at android.app.ActivityThread.-wrap14 (ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1642)
  at android.os.Handler.dispatchMessage (Handler.java:102)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6776)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1496)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1386)
Caused by: java.lang.NullPointerException: 
  at com.mycompany.fragment.FragmentB.onActivityCreated (FragmentB.java:35)
  at android.support.v4.app.Fragment.performActivityCreated (Fragment.java:2089)
  at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManagerImpl.java:1133)
  at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManagerImpl.java:1290)
  at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManagerImpl.java:1272)
  at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated (FragmentManagerImpl.java:2149)
  at android.support.v4.app.FragmentController.dispatchActivityCreated (FragmentController.java:201)
  at android.support.v4.app.FragmentActivity.onStart (FragmentActivity.java:600)
  at android.support.v7.app.AppCompatActivity.onStart (AppCompatActivity.java:178)
  at android.app.Instrumentation.callActivityOnStart (Instrumentation.java:1256)
  at android.app.Activity.performStart (Activity.java:6972)
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2937)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3045)
  at android.app.ActivityThread.-wrap14 (ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1642)
  at android.os.Handler.dispatchMessage (Handler.java:102)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6776)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1496)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1386)
答案

长期存在的静态成员存在问题,因为Android可能已释放内存并在某个时间删除了此值(当没有片段处于活动状态时引用它)。你还没有明确说过你是否可以在没有首先从FragmentA设置值的情况下访问FragmentB,所以这也可能是你的问题。

附加说明 - 常量应该是常量 - 所以应该有final关键字。

我建议的解决方案是摆脱这种糟糕的架构,其中两个组件依赖外部神对象来维持其状态。将您的枚举值作为意图中的Extra传递。

你可以写入包

public static final String KEY_ENUM = "MyEnumKey";

bundle.putString(KEY_ENUM, myEnum.name()):

然后用它读回来

Bundle bundle = intent.getExtras();
MyEnumTypemyEnum = MyEnumType.valueOf(bundle.getString(FragmentA.KEY_ENUM));

另一个建议是确保myEnum永远不为null(默认情况下是这样)。声明如下:

private static MyEnumType mMyEnum = MyEnumType.MY_DEFAULT_VALUE;

以上是关于实用工具类的静态成员(null)生命周期的主要内容,如果未能解决你的问题,请参考以下文章

C语言中,哪种存储类的作用域与生命周期是不一致的?

C++:static类

类的生命周期

第25课 类的静态成员变量

练习7.567.58

java 静态变量生命周期(类生命周期)