2015-09-26 31 views
0

我遇到了奇怪的行爲和NullPointerException(有時)用在Activity一個Singleton模式。安卓:活動週期和辛格爾頓

清單中(聲明的方向橫向)的活動:

<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傳遞給單身和它存儲爲類的成員。在活動的onDestroy()處刪除interface

活動的生命週期和原木:

#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方法被稱爲excpeted的訂單和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) 

正如你可以看到,步驟先前的步驟。在onDestroy之前調用onCreate。此外,我已經添加了一些(中國科學院#N),這表明有多少活動實例越來越創建,這是越來越摧毀。

根據日誌,總共有而我鎖定/解鎖的手機,它越來越創建3個不同的活動實例。這個問題是由最後一步造成的,當第三個活動(inst#3)被創建,並且第二個活動(inst#2)被銷燬時。我使用的是Singleton(僅1個實例存在於整個應用程序)來處理事件和管理遊戲,在活動的onDestroySingleton預計,比賽已經結束,它必須刪除對活動的引用。這樣一來,如果事件發生在比賽中NullPointerException被拋出,因爲Singleton已清除所有引用。

  1. 我應該使用不同於Singleton的方法嗎? (如何處理遊戲事件?)
  2. 我應該使用onSave/onRestore實例嗎? (爲什麼和如何?)
  3. 我應該onPause/onResume而不是onCreate/onDestroy?
  4. 出於想法。如果你有什麼好主意,歡迎如何解決這個問題。

回答

0

我認爲你應該創建一個新的類來擴展應用程序,並在onCreate()方法中初始化你的單例。

public class MyApplication extends Application { 

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

在您的清單,在應用程序標籤中,添加機器人:名字=「MyApplication的」 在任何有更好的單線程安全的,因爲你的costructor,我建議你創建一個靜態istance你的對象在應用程序中。

public class MyApplication extends Application { 

public static GameManager gameManager = new GameManager(); 

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

而後就可以通過

MyApplication.gameManager 

這是有一個單獨的線程安全

最好的辦法打電話給你單身