日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

MVPArms框架学习遇到的一个问题——普通Activity配合Fragment出现空指针

發(fā)布時(shí)間:2023/12/9 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MVPArms框架学习遇到的一个问题——普通Activity配合Fragment出现空指针 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

MVPArms

一個(gè)整合了大量主流開(kāi)源項(xiàng)目高度可配置化的 Android MVP 快速集成框架

https://github.com/JessYanCoding/MVPArms
為了簡(jiǎn)化開(kāi)發(fā),使用了MVPArms作為開(kāi)發(fā)框架,同時(shí)也是學(xué)習(xí)封裝的一個(gè)經(jīng)典樣板。

我也是在努力吸收其精華中,在使用中遇到一個(gè)空指針的問(wèn)題,然后debug調(diào)試下,順藤摸瓜找到了線(xiàn)索。

問(wèn)題是這樣的,一個(gè)Activity +ViewPager 去加載Fragment,Fragment使用框架提供的BaseFragment去實(shí)現(xiàn)MVP,請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù) 并綁定Fragment的生命周期。看似正常的操作下卻隱藏著一個(gè)致命的bug ,我斷開(kāi)網(wǎng)絡(luò),關(guān)閉界面,本應(yīng)解綁銷(xiāo)毀的Observer卻沒(méi)解綁,從而執(zhí)行了doFinally,而此時(shí)mRootView已經(jīng)銷(xiāo)毀,因此引發(fā)了空指針問(wèn)題。

看到崩潰 很是郁悶,納悶為何沒(méi)有執(zhí)行銷(xiāo)毀呢?跟進(jìn)RxLifecycleUtils.bindToLifecycle(mRootView)也看到返回了結(jié)果,也就是說(shuō)此操作是成功的。我們來(lái)看一下這里執(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í)簡(jiǎn)單來(lái)講就是 它既是觀察者 又是 被觀察者,你可以用它來(lái)實(shí)現(xiàn)簡(jiǎn)單的EventBus,詳細(xì)可搜索RxBus。

好,繼續(xù)往下,知道了生命周期的是怎么發(fā)送的了,就得往下找是 在哪 發(fā)送的。
點(diǎn)擊方法,看看都是那些地方使用了咱們的Subject

最后那三個(gè)是 綁定時(shí)候用的,剛才咱們見(jiàn)過(guò) RxLifecycleUtils了,他就是個(gè)Utils,給我們開(kāi)發(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接口,不然就沒(méi)有Subject),來(lái)看obtainSubject()方法

private Subject<FragmentEvent> obtainSubject(Fragment fragment) {return ((FragmentLifecycleable) fragment).provideLifecycleSubject();}

就是拿到我們剛才說(shuō)的Subject。自己發(fā)給自己- _ -。 好,在哪發(fā) 和 在哪接收 的事件 都找到了,那為啥我沒(méi)收到事件呢?莫急,繼續(xù)看一下FragmentLifecycleForRxLifecycle在哪里使用到了。

除了第一個(gè)ActivityLifecycleForRxLifecycle 為自己創(chuàng)建的類(lèi),其他均為Dagger2自己生成的,所以直接來(lái)看ActivityLifecycleForRxLifecycle,Duang~~

聰明的你一眼就看出問(wèn)題來(lái)了,是的,只有滿(mǎn)足兩個(gè)條件方能完成對(duì)Fragment生命周期回調(diào)的注冊(cè)

@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,并沒(méi)有實(shí)現(xiàn)ActivityLifecycleable,因?yàn)?這個(gè)Activity不做數(shù)據(jù)請(qǐng)求,只負(fù)責(zé)界面管理,資源可控。所以原因就是 Fragment的生命周期沒(méi)有監(jiān)聽(tīng)到。那么就好辦了 實(shí)現(xiàn)ActivityLifecycleable 唄。不過(guò) 在仔細(xì)瞅瞅,發(fā)現(xiàn)BaseActivity 的注釋

/**
* ================================================
* 因?yàn)?Java 只能單繼承,所以如果要用到需要繼承特定 {@link Activity} 的三方庫(kù),那你就需要自己自定義 {@link Activity}
* 繼承于這個(gè)特定的 {@link Activity},然后再按照 {@link BaseActivity} 的格式,將代碼復(fù)制過(guò)去,記住一定要實(shí)現(xiàn){@link IActivity}
* ================================================
*/
以及 useFragment 的注釋

/*** 這個(gè)Activity是否會(huì)使用Fragment,框架會(huì)根據(jù)這個(gè)屬性判斷是否注冊(cè){@link android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks}* 如果返回false,那意味著這個(gè)Activity不需要綁定Fragment,那你再在這個(gè)Activity中綁定繼承于 {@link com.jess.arms.base.BaseFragment} 的Fragment將不起任何作用** @return*/@Overridepublic boolean useFragment() {return true;}

發(fā)現(xiàn) 在ActivityLifecycle(Application.ActivityLifecycleCallbacks 默認(rèn)實(shí)現(xiàn)類(lèi))的
onActivityCreated()方法中registerFragmentCallbacks(Activity activity)通過(guò)判斷是否實(shí)現(xiàn)了IActivity以及userFragment==true 來(lái)進(jìn)行注冊(cè)Fragment 生命周期的監(jiān)聽(tīng),不過(guò)這里指的是Fragment正常生命周期,而非是RxLifecycle

private void registerFragmentCallbacks(Activity activity) {boolean useFragment = activity instanceof IActivity ? ((IActivity) activity).useFragment() : true;if (activity instanceof FragmentActivity && useFragment) {((FragmentActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(mFragmentLifecycle.get(), true);if (mExtras.containsKey(ConfigModule.class.getName())) {List<ConfigModule> modules = (List<ConfigModule>) mExtras.get(ConfigModule.class.getName());for (ConfigModule module : modules) {module.injectFragmentLifecycle(mApplication, mFragmentLifecycles.get());}mExtras.remove(ConfigModule.class.getName());}//注冊(cè)框架外部, 開(kāi)發(fā)者擴(kuò)展的 Fragment 生命周期邏輯for (FragmentManager.FragmentLifecycleCallbacks fragmentLifecycle : mFragmentLifecycles.get()) {((FragmentActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(fragmentLifecycle, true);}}}

所以說(shuō)到底,實(shí)現(xiàn)ActivityLifecycleable 即可。

其實(shí) 這個(gè)問(wèn)題 是我沒(méi)有 認(rèn)真 閱讀源碼 導(dǎo)致,不過(guò)也借此了解了框架的是如何實(shí)現(xiàn)生命周期的監(jiān)聽(tīng)。

MVPArms 框架 很優(yōu)秀,實(shí)際開(kāi)發(fā)中擇需使用,單這封裝思想得讓我學(xué)上好一段時(shí)間。 ヾ(?°?°?)ノ゙ 加油 ——記一次崩潰調(diào)查。

總結(jié)

以上是生活随笔為你收集整理的MVPArms框架学习遇到的一个问题——普通Activity配合Fragment出现空指针的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。