MVPArms框架学习遇到的一个问题——普通Activity配合Fragment出现空指针
MVPArms
一個(gè)整合了大量主流開源項(xiàng)目高度可配置化的 Android MVP 快速集成框架
https://github.com/JessYanCoding/MVPArms
為了簡化開發(fā),使用了MVPArms作為開發(fā)框架,同時(shí)也是學(xué)習(xí)封裝的一個(gè)經(jīng)典樣板。
我也是在努力吸收其精華中,在使用中遇到一個(gè)空指針的問題,然后debug調(diào)試下,順藤摸瓜找到了線索。
問題是這樣的,一個(gè)Activity +ViewPager 去加載Fragment,Fragment使用框架提供的BaseFragment去實(shí)現(xiàn)MVP,請求網(wǎng)絡(luò)數(shù)據(jù) 并綁定Fragment的生命周期。看似正常的操作下卻隱藏著一個(gè)致命的bug ,我斷開網(wǎng)絡(luò),關(guān)閉界面,本應(yīng)解綁銷毀的Observer卻沒解綁,從而執(zhí)行了doFinally,而此時(shí)mRootView已經(jīng)銷毀,因此引發(fā)了空指針問題。
看到崩潰 很是郁悶,納悶為何沒有執(zhí)行銷毀呢?跟進(jìn)RxLifecycleUtils.bindToLifecycle(mRootView)也看到返回了結(jié)果,也就是說此操作是成功的。我們來看一下這里執(zhí)行了什么操作
public static <T> LifecycleTransformer<T> bindToLifecycle(@NonNull IView view) {Preconditions.checkNotNull(view, "view == null");if (view instanceof Lifecycleable) {return bindToLifecycle((Lifecycleable) view);} else {throw new IllegalArgumentException("view isn't Lifecycleable");}}繼續(xù)跟進(jìn)
public static <T> LifecycleTransformer<T> bindToLifecycle(@NonNull Lifecycleable lifecycleable) {Preconditions.checkNotNull(lifecycleable, "lifecycleable == null");if (lifecycleable instanceof ActivityLifecycleable) {return RxLifecycleAndroid.bindActivity(((ActivityLifecycleable) lifecycleable).provideLifecycleSubject());} else if (lifecycleable instanceof FragmentLifecycleable) {return RxLifecycleAndroid.bindFragment(((FragmentLifecycleable) lifecycleable).provideLifecycleSubject());} else {throw new IllegalArgumentException("Lifecycleable not match");}}可以看到 實(shí)現(xiàn) FragmentLifecycleable接口的Activity/Fragment都執(zhí)行了provideLifecycleSubject(),這是一個(gè)接口提供的方法,為Activity/Fragment實(shí)現(xiàn)RxLifecycle進(jìn)行的規(guī)范。
查閱BaseFragment/BaseActivity
發(fā)現(xiàn)其提供了的是一個(gè)Subject,啥?你不知道啥是Subject?給你的地址:
https://mcxiaoke.gitbooks.io/rxdocs/content/Subject.html
其實(shí)簡單來講就是 它既是觀察者 又是 被觀察者,你可以用它來實(shí)現(xiàn)簡單的EventBus,詳細(xì)可搜索RxBus。
好,繼續(xù)往下,知道了生命周期的是怎么發(fā)送的了,就得往下找是 在哪 發(fā)送的。
點(diǎn)擊方法,看看都是那些地方使用了咱們的Subject
最后那三個(gè)是 綁定時(shí)候用的,剛才咱們見過 RxLifecycleUtils了,他就是個(gè)Utils,給我們開發(fā)綁定用的,看上面兩個(gè)的定義 也能知道個(gè)是做什么的,這就很符合命名規(guī)范(笑)。
- ActivityLifecycleForRxLifecycle
接收到Activity生命周期時(shí) 發(fā)送事件 通知 做了RxLifecycle相關(guān)綁定的觀察者
- FragmentLifecycleForRxLifecycle
接收到Fragment生命周期時(shí) 發(fā)送事件 通知 做了RxLifecycle相關(guān)綁定的觀察者
點(diǎn)進(jìn)去一看,果不其然
里面分發(fā)了各個(gè)生命周期事件(前提是Fragment實(shí)現(xiàn)了FragmentLifecycleable接口,不然就沒有Subject),來看obtainSubject()方法
private Subject<FragmentEvent> obtainSubject(Fragment fragment) {return ((FragmentLifecycleable) fragment).provideLifecycleSubject();}就是拿到我們剛才說的Subject。自己發(fā)給自己- _ -。 好,在哪發(fā) 和 在哪接收 的事件 都找到了,那為啥我沒收到事件呢?莫急,繼續(xù)看一下FragmentLifecycleForRxLifecycle在哪里使用到了。
除了第一個(gè)ActivityLifecycleForRxLifecycle 為自己創(chuàng)建的類,其他均為Dagger2自己生成的,所以直接來看ActivityLifecycleForRxLifecycle,Duang~~
聰明的你一眼就看出問題來了,是的,只有滿足兩個(gè)條件方能完成對Fragment生命周期回調(diào)的注冊
@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {if (activity instanceof ActivityLifecycleable) {obtainSubject(activity).onNext(ActivityEvent.CREATE);if (activity instanceof FragmentActivity) {((FragmentActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(mFragmentLifecycle.get(), true);}}}而我外部的Activity只是 AppCompatActivity,并沒有實(shí)現(xiàn)ActivityLifecycleable,因?yàn)?這個(gè)Activity不做數(shù)據(jù)請求,只負(fù)責(zé)界面管理,資源可控。所以原因就是 Fragment的生命周期沒有監(jiān)聽到。那么就好辦了 實(shí)現(xiàn)ActivityLifecycleable 唄。不過 在仔細(xì)瞅瞅,發(fā)現(xiàn)BaseActivity 的注釋
/**
* ================================================
* 因?yàn)?Java 只能單繼承,所以如果要用到需要繼承特定 {@link Activity} 的三方庫,那你就需要自己自定義 {@link Activity}
* 繼承于這個(gè)特定的 {@link Activity},然后再按照 {@link BaseActivity} 的格式,將代碼復(fù)制過去,記住一定要實(shí)現(xiàn){@link IActivity}
* ================================================
*/
以及 useFragment 的注釋
發(fā)現(xiàn) 在ActivityLifecycle(Application.ActivityLifecycleCallbacks 默認(rèn)實(shí)現(xiàn)類)的
onActivityCreated()方法中registerFragmentCallbacks(Activity activity)通過判斷是否實(shí)現(xiàn)了IActivity以及userFragment==true 來進(jìn)行注冊Fragment 生命周期的監(jiān)聽,不過這里指的是Fragment正常生命周期,而非是RxLifecycle
所以說到底,實(shí)現(xiàn)ActivityLifecycleable 即可。
其實(shí) 這個(gè)問題 是我沒有 認(rèn)真 閱讀源碼 導(dǎo)致,不過也借此了解了框架的是如何實(shí)現(xiàn)生命周期的監(jiān)聽。
MVPArms 框架 很優(yōu)秀,實(shí)際開發(fā)中擇需使用,單這封裝思想得讓我學(xué)上好一段時(shí)間。 ヾ(?°?°?)ノ゙ 加油 ——記一次崩潰調(diào)查。
總結(jié)
以上是生活随笔為你收集整理的MVPArms框架学习遇到的一个问题——普通Activity配合Fragment出现空指针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CPP第四版第四章:创建动态数组
- 下一篇: npm 安装 chromedriver