Activity后台運行一段時間回來crash問題的分析與解決


最近做項目的時候碰到一個棘手的問題,花了不少時間才找到原因並解決。特此記錄這個被我踩過的坑,希望其他朋友遇到此問題不要調到這坑里去了。

問題描述:

      1、背景:我的app中某個界面的Activity是繼承FragmentActivity,因為此界面包含兩個Fragment。這里我稱為FragmentA和FragmentB吧。在Activity中有個刷新按鈕,用來刷新ViewPager當前Fragment內容的刷新。點擊Activity的刷新按鈕之后,刷新按鈕需要有簡單的旋轉動畫,等Fragment里面的刷新結束之后,會使用getActivity通知Activity結束刷新按鈕的刷新動畫。以上就是我的業務場景,說簡單點就是Fragment需要與它附屬的Activity進行通信。

  2、問題:當應用程序運行到該Activity時,按Home鍵將該應用程序放置后台運行,去其他app轉轉。一段時間后,又回到該應用程序,還是在之前的那個Activity。這時我想刷新一下Fragment里面的內容,點擊了Activity界面上的刷新按鈕,結果程序crash了。

 

問題分析:

  剛開始遇到該問題時,查看奔潰日志,發現是空指針異常。因為這種場景不多,所以只是簡單的加上非空判斷就沒在意這個問題了。到后面換了個測試機器,配置不是很好(只有512M運行內存),結果此問題頻繁地出現,開始引起我的重視了。由於經驗不是很足,此問題不知道怎么重現,所以很難找出問題的根本原因。后來終於在網上找到了一篇和我遇到同樣問題的朋友的帖子,才知道出現這個問題的原因所在。

  原來Activity切換到后台之后,由於內存不夠,此Activity被系統回收了,一段時間之后回到該應用程序,Activity被重新實例化了。而Activity被系統銷毀時,附屬在該Activity的Fragment並沒有被銷毀,在Activity的onSaveInstanceState里面將Fragment狀態保存起來了,所以Activity重新創建了,但是FragmentA和FragmentB還是之前的,而此時FragmentA和FragmentB所附屬的Activity已經被系統回收了,這次再調用getActivity時返回了null,才導致上面問題的出現。

  我們看看FragmentActivity源碼中的onSaveInstanceState方法:

1 protected void onSaveInstanceState(Bundle outState)
2    {
3      super.onSaveInstanceState(outState);
4      Parcelable p = mFragments.saveAllState();
5      if (p != null) {
6        outState.putParcelable("android:support:fragments", p);
7     }
8    }

  由上面源碼可以看出,FragmentActivity確實在onSaveInstanceState方法里面將Fragment的狀態保存了。

 

問題解決:

  知道問題的原因了,就好辦了。解決方法其實很簡單,我們只要讓FragmentActivity被系統回收的時候,不保存Fragment的狀態即可,即在FragmentActivity中重寫onSaveInstanceState方法,並且注釋掉super.onSaveInstanceState(outState)就行了。

1     @Override
2     protected void onSaveInstanceState(Bundle outState) {
3 //        super.onSaveInstanceState(outState);
4     }

 

總結:

  1、程序出現問題時,要先找出出現此問題的原因,對症下葯才能從根本上解決問題。

  2、對於Activity被系統回收導致的問題,可以使用切換橫豎屏來模擬場景。

 

最后感謝寫http://my.oschina.net/u/1011854/blog/469138這篇帖子的朋友。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM