在調用 getLifecycle().addObserver()
的時候報出這樣的錯誤java
java.lang.IllegalArgumentException at androidx.lifecycle.LifecycleRegistry.upEvent(SourceFile:279) at androidx.lifecycle.LifecycleRegistry.forwardPass(SourceFile:293) at androidx.lifecycle.LifecycleRegistry.sync(SourceFile:333) at androidx.lifecycle.LifecycleRegistry.addObserver(SourceFile:189)
問題代碼出如今這裏 LifecycleRegisty
這個類中,代碼以下android
private static Event upEvent(State state) { switch (state) { case INITIALIZED: case DESTROYED: return ON_CREATE; case CREATED: return ON_START; case STARTED: return ON_RESUME; case RESUMED: throw new IllegalArgumentException(); } throw new IllegalArgumentException("Unexpected state value " + state); }
當傳入的狀態是 RESUMED
的時候能夠就會拋出錯誤,而調用這個方法的代碼以下bash
@Override public void addObserver(LifecycleObserver observer) { State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); if (previous != null) { return; } boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent; State targetState = calculateTargetState(observer); mAddingObserverCounter++; while ((statefulObserver.mState.compareTo(targetState) < 0 && mObserverMap.contains(observer))) { pushParentState(statefulObserver.mState); // 這裏調用 statefulObserver.dispatchEvent(mLifecycleOwner, upEvent(statefulObserver.mState)); popParentState(); // mState / subling may have been changed recalculate targetState = calculateTargetState(observer); } if (!isReentrance) { // we do sync only on the top level. sync(); } mAddingObserverCounter--; }
由於在 State
是個枚舉類型 ,RESUME
排在最後,因此是最大的多線程
public enum State { // 刪除了無用註釋 DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; }
也就是說,如下代碼中ide
while ((statefulObserver.mState.compareTo(targetState) < 0&& mObserverMap.contains(observer))) { pushParentState(statefulObserver.mState); statefulObserver.dispatchEvent(mLifecycleOwner, upEvent(statefulObserver.mState)); popParentState(); // mState / subling may have been changed recalculate targetState = calculateTargetState(observer); } }
若是你想進入循環而且知足調用 upEvent()
發生崩潰的 statefulObserver.mState
值是不存在的,由於 upEvent()
須要 statefulObserver.mState
的值等於RESUMED
, 可是 statefulObserver.mState.compareTo(targetState) < 0
這個恰好就不能是這個條件,RESUMED
是最大的 state
值,是不可能存在其餘值比較以後小於0的。spa
當出現這種先後矛盾的時候,大機率就是多線程調用致使了。線程
這個時候咱們就要開始找,還有什麼別的方法會致使 statefulObserver.mState
的改變,經過 IDE 的 find usage
能夠輕鬆找到 mState
修改只有下圖中的兩處
咱們忽略構建方法(由於每次構建的對象不同,不可能同時改),專心再找 dispatchEvent
的使用
排除 addObserver
,重心放在 forwardPass
和 backwardPass
,他們統一調用的方法就是 sync
,經過斷點調試就能發現LifeCycleOwner
生命週期改變的時候會調用這個方法。也就是說,若是我使用非UI線程調用 addOboserver
同時改變生命週期就能達到崩潰的條件。調試
咱們在兩個地方設置斷點,分別是
code
而後在 onResume
增長代碼server
override fun onResume(){ super.onResume() Thread { lifecycle.addObserver(new ObserverImp()) }.start() }
由於出錯的狀態是 RESUMED
, 因此你只要 RESUMED
的時候加入 Oboserver
才能獲得生命週期報錯。操做路徑是 App 後臺返回前臺顯示,而後你就會看到
兩個線程的顯示不是一開始就有的,須要點多幾下過,由於須要生命週期調用 addObserver 以後纔會開始新線程
這個時候咱們只須要操做 UI 線程停在 RESUME
便可,以下圖
這個時候咱們切換到另一個線程, statefulObserver.mState
值就是 RESUME
這個時候點擊下一步就是崩潰了。
條件矛盾大機率是線程問題,剩下就是怎麼構造多線程修改條件。