Android:活动生命周期和Singleton

时间:2015-09-26 10:39:33

标签: android singleton android-lifecycle

我遇到了奇怪的行为,NullPointerException(有时候)在Singleton中使用了Activity模式。

清单中的活动(声明了方向格局):

<activity
   android:name="com.lux.game.MainActivity"
   android:screenOrientation="landscape" />

活动类:

private GameManager.OnEventListener mEventListener = new GameManager.OnEventListener {
   @Override
   public void onEvent(Event event) {
      if (event == Event.PLAYER_SELECTED_PUZZLE) {
         // Do something on the UI
      }
   }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    // If the orientation is landscape, then initialize the Game Manager
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
       GameManager.getInstance().init();

       // Register an interface to deal with game events
       GameManager.getInstance().registerForEvent(mEventListener);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();

    // The activity was destroyed, remove the interface and clear the references
    GameManager.getInstance().cleanUp();
}

GameManager单身人士:

public class GameManager {
   private static GameManager mInstance;

   private GameManager() {
   }

   public static synchronized getInstance() {
      if (mInstance == null) {
          mInstance = new GameManager();
      }

      return mInstance;
   }
}

正如你所看到的,我正在使用GameManager单身来处理游戏事件(玩家选择一张牌,游戏结束等)。如果方向是横向的并且onCreate()被传递给单例并且它被存储为类的成员,则单例在interface处被实例化。活动interface已删除onDestroy()

活动生命周期和日志:

#1 onCreate(), orientation: LANDSCAPE
#2 back button pressed
#3 onDestroy(), orientation: PORTRAIT

一切都按预期工作,直到我开始通过锁定/解锁测试应用程序并按下设备上的 HOME 按钮(真实设备,而不是模拟器)

活动生命周期和日志:

#1 onCreate(), orientation: LANDSCAPE
#2 lock phone
#3 onDestroy(), orientation: PORTRAIT
#4 onCreate(), orientation: PORTRAIT
#5 unlock phone
#6 onDestroy(), orientation: PORTRAIT
#7 onCreate(), orientation: LANDSCAPE

onCreateonDestroy被称为服务器时间(正常行为,因为方向更改),但这不会产生问题,因为活动的lifecycle方法在中被调用已删除},并且interface已删除,我不会留下任何可能导致内存泄漏的引用。

如果以不同的顺序调用上述步骤,问题(有时)会浮出水面:

#1 onCreate(), orientation: LANDSCAPE (inst #1)
#2 lock phone
#3 onDestroy(), orientation: PORTRAIT (inst #1)
#4 onCreate(), orientation: PORTRAIT (inst #2)
#5 unlock phone
#6 onCreate(), orientation: LANDSCAPE (inst #3)
#7 onDestroy(), orientation: PORTRAIT (inst #2)

如您所见,与前面的步骤相比,步骤 6 7 是反向的。在onCreate之前调用onDestroy。我还添加了一个数字(inst #N),它表示创建了多少个活动实例,哪些活动实例被销毁。

根据日志,当我锁定/解锁手机时,总共创建了3个不同的活动实例。问题是由最后一步引起的,当第三个活动(inst#3)被创建,第二个活动(inst#2)被破坏时。我正在使用Singleton(整个应用程序中只存在1个实例)来处理事件和管理游戏,活动的onDestroy Singleton期望游戏结束,并且它必须删除对活动的引用。这样,如果游戏中发生了事件,则NullPointerException被抛出,因为Singleton已清除所有引用。

  1. 我应该使用与Singleton不同的方法吗? (如何处理游戏事件?)
  2. 我应该使用onSave / onRestore实例吗? (为什么以及如何?)
  3. 我应该onPause / onResume而不是onCreate / onDestroy吗?
  4. 出于想法。如果你有任何好主意如何解决这个问题,欢迎。

1 个答案:

答案 0 :(得分:1)

我认为你应该创建一个新的类来扩展Application并在它们的onCreate()元文件中启动你的Singleton。

public class MyApplication extends Application {

@Override
public void onCreate() {
    super.onCreate();
    GameManager.getInstance().init();
    }
}

在您的清单中,在应用标记中添加 android:name =&#34; MyApplication&#34; 在任何有更好的单例线程安全的情况下,由于你的构造函数,我建议你在应用程序中创建一个静态的isjet。

public class MyApplication extends Application {

public static GameManager gameManager = new GameManager();

@Override
public void onCreate() {
    super.onCreate();
    gameManager.init();
    }
}

然后你可以通过

打电话给你的单身人士
MyApplication.gameManager

这是使单例线程安全的最佳方法