fragmentation框架pop方法引起Can not perform this action after onSaveInstanceState異常處理

項(xiàng)目踩坑記錄

????????項(xiàng)目使用fragmentation框架茎匠,有個(gè)業(yè)務(wù)場(chǎng)景是通過(guò)異步掃描(耗時(shí)操作)進(jìn)行綁定吁朦,如果60秒超時(shí)則自動(dòng)關(guān)閉該頁(yè)面忍啤,該頁(yè)面是一個(gè)fragment编检,在框架里調(diào)用pop()方法就可以關(guān)閉胎食;在正常情況下是沒(méi)有問(wèn)題的,但是如果在60秒的過(guò)程中手機(jī)自動(dòng)熄屏或者鎖屏允懂、home鍵等操作厕怜,當(dāng)60秒時(shí)間到達(dá),調(diào)用pop()時(shí)就會(huì)出現(xiàn)異常:

FATAL EXCEPTION: main

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1842)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:775)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? at me.yokeyword.fragmentation.FragmentationDelegate.debouncePop(FragmentationDelegate.java:500)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? at me.yokeyword.fragmentation.FragmentationDelegate.back(FragmentationDelegate.java:487)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? at me.yokeyword.fragmentation.SupportFragment.pop(SupportFragment.java:652)



第一反應(yīng)查看 Can not perform this action after onSaveInstanceState這個(gè)問(wèn)題蕾总,通過(guò)查看pop()方法源碼:

SupportFragment類中:

接著看back()方法粥航,跳到FragmentationDelegate類中的方法:

注意到紅框中的方法,點(diǎn)過(guò)去

在FragmentManager類中

這是一個(gè)抽象類生百,那在哪里有它的實(shí)現(xiàn)呢递雀,往下翻


終于在這個(gè)實(shí)現(xiàn)類中找到了這個(gè)方法:



紅框中那熟悉的味道

原來(lái)是這里拋出了異常,那為什么會(huì)有異常呢蚀浆,從這句異常的提示中我們注意到了這個(gè)方法onSaveInstanceState();原來(lái)手機(jī)自動(dòng)熄屏或者鎖屏缀程、home鍵等操作會(huì)觸發(fā)這個(gè)回調(diào),以防應(yīng)用被殺死后能迅速恢復(fù)到之前的狀態(tài)市俊,這個(gè)方法具體的說(shuō)明可以去閱讀Activity中的源碼杠输。那如何避免這個(gè)異常呢?網(wǎng)上對(duì)于這個(gè)異常的處理有很多秕衙,可參考http://blog.csdn.net/EdisonChang/article/details/49873669

大多是在activity中對(duì)onBackPressed()方法的處理蠢甲,或者直接重寫onSaveInstanceState(),這些方法大多粗暴据忘,要么不能存儲(chǔ)狀態(tài)鹦牛,要么不能在farament中使用搞糕。

我們的項(xiàng)目使用的是單一Activity加多Fragment這種架構(gòu)(現(xiàn)在發(fā)現(xiàn)有很多缺陷),一開始在onSaveInstanceState()方法中嘗試用反射的方法去更改mStateSaved的狀態(tài)為false來(lái)防止異常的拋出曼追,但是發(fā)現(xiàn)在pop()之前會(huì)調(diào)用saveAllState()和dispatchStop()窍仰,這些方法中又將mStateSaved重置為true,換個(gè)思路來(lái)想礼殊,既然我們要解決的pop()時(shí)的問(wèn)題驹吮,那么可以重寫pop(),在調(diào)用父類方法前對(duì)mStateSaved進(jìn)行賦值晶伦,從而避免異常的拋出碟狞,而不需要去考慮什么時(shí)候執(zhí)行了onSaveInstanceState()方法;

@Override

public void pop() {

if(!isSupportVisible()){

invokeFragmentManagerNoteStateNotSaved();

? }

super.pop();

}

private MethodnoteStateNotSavedMethod;

private ObjectfragmentMgr;

private String[]activityClassName = {"Activity", "FragmentActivity"};

public void invokeFragmentManagerNoteStateNotSaved() {

//java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

? if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {

return;

? }

try {

if (noteStateNotSavedMethod !=null &&fragmentMgr !=null) {

noteStateNotSavedMethod.invoke(fragmentMgr);

return;

? ? ? }

Class cls =_mActivity. getClass();

? ? ? do {

cls = cls.getSuperclass();

? ? ? }while (!(activityClassName[0].equals(cls.getSimpleName())

||activityClassName[1].equals(cls.getSimpleName())));

? ? ? Field fragmentMgrField = prepareField(cls, "mFragments");

? ? ? if (fragmentMgrField !=null) {

fragmentMgr = fragmentMgrField.get(getActivity());

? ? ? ? noteStateNotSavedMethod = getDeclaredMethod(fragmentMgr, "noteStateNotSaved");

? ? ? ? if (noteStateNotSavedMethod !=null) {

noteStateNotSavedMethod.invoke(fragmentMgr);

? ? ? ? }

}

}catch (Exception ex) {

}

}

private FieldprepareField(Class c, String fieldName)throws NoSuchFieldException {

while (c !=null) {

try {

Field f = c.getDeclaredField(fieldName);

? ? ? ? f.setAccessible(true);

? ? ? ? return f;

? ? ? }finally {

c = c.getSuperclass();

? ? ? }

}

throw new NoSuchFieldException();

}

private MethodgetDeclaredMethod(Object object, String methodName, Class... parameterTypes) {

Method method =null;

? for (Class clazz = object.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {

try {

method = clazz.getDeclaredMethod(methodName, parameterTypes);

? ? ? ? return method;

? ? ? }catch (Exception e) {

}

}

return null;

}

通過(guò)fragmentation中isSupportVisible()方法可以判斷出是否是不可見狀態(tài)婚陪,如果是的話調(diào)用反射方法族沃,當(dāng)然如果簡(jiǎn)單粗暴一點(diǎn)可以連isSupportVisible()都不判斷,畢竟在屏幕旋轉(zhuǎn)時(shí)這個(gè)方法是不會(huì)觸發(fā)的泌参,而會(huì)調(diào)用onSaveInstanceState()脆淹,引起異常,我們項(xiàng)目中是禁止屏幕旋轉(zhuǎn)的沽一,所以不考慮這種情況盖溺。

對(duì)于反射大致解釋一下,通過(guò)反射FragmentActivity類铣缠,拿到“mFragments”這個(gè)變量咐柜,這個(gè)變量為FragmentController類型,再反射FragmentController類中的noteStateNotSaved方法攘残,


mHost.mFragmentManager就是FragmentManagerImpl拙友,


從而將mStateSaved置為false

現(xiàn)在就可以從容的在熄屏,home狀態(tài)下pop()啦歼郭。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遗契,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子病曾,更是在濱河造成了極大的恐慌牍蜂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泰涂,死亡現(xiàn)場(chǎng)離奇詭異鲫竞,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)逼蒙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門从绘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事僵井∩陆兀” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵批什,是天一觀的道長(zhǎng)农曲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)驻债,這世上最難降的妖魔是什么乳规? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮合呐,結(jié)果婚禮上瞎颗,老公的妹妹穿的比我還像新娘昂儒。我一直安慰自己绕娘,他們只是感情好锯七,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布源织。 她就那樣靜靜地躺著翩伪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谈息。 梳的紋絲不亂的頭發(fā)上缘屹,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音侠仇,去河邊找鬼轻姿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛逻炊,可吹牛的內(nèi)容都是我干的互亮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼余素,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼豹休!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起桨吊,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤威根,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后视乐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洛搀,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年佑淀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了留美。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖独榴,靈堂內(nèi)的尸體忽然破棺而出僧叉,到底是詐尸還是另有隱情,我是刑警寧澤棺榔,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布瓶堕,位于F島的核電站,受9級(jí)特大地震影響症歇,放射性物質(zhì)發(fā)生泄漏郎笆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一忘晤、第九天 我趴在偏房一處隱蔽的房頂上張望宛蚓。 院中可真熱鬧,春花似錦设塔、人聲如沸凄吏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)痕钢。三九已至,卻和暖如春序六,著一層夾襖步出監(jiān)牢的瞬間任连,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工例诀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留随抠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓繁涂,卻偏偏與公主長(zhǎng)得像拱她,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扔罪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容