Android架構(gòu)設(shè)計(jì)-簡(jiǎn)單粗暴,搞定MVP網(wǎng)絡(luò)請(qǐng)求內(nèi)存泄漏

一、使用Mvp為什么怎么開(kāi)始內(nèi)存內(nèi)存泄漏了?

我們先簡(jiǎn)單的看一段Presenter層的代碼

 override fun requestData(isRefresh: Boolean, type: String) {
        val call: Call<BaseResponse<Data>> = RequestManager.getInstance().apiService.getData(type)

        call.enqueue(object : Callback<BaseResponse<Data>> {
            override fun onFailure(call: Call<BaseResponse<Data>>, t: Throwable) {
                view.responseData(false, hasMore = false, cards = null, isRefresh = isRefresh)
            }

            override fun onResponse(call: Call<BaseResponse<Data>>, response: Response<BaseResponse<Data>>) {
                if (response.body() != null) {
                    if (response.body()?.state == 200) {
                       view.responseChannelData(true, hasMore = hasMore, cards = response.body()?.data, isRefresh = isRefresh)
                    }
                }
            }
        })
    }
}

大體上這段代碼是完成一個(gè)單次的網(wǎng)絡(luò)請(qǐng)求,然后進(jìn)行回調(diào)的過(guò)程,那么網(wǎng)絡(luò)操作是一個(gè)耗時(shí)操作,我們不知道請(qǐng)求什么時(shí)候可以回來(lái)。

場(chǎng)景模擬:比如說(shuō)現(xiàn)在是一個(gè)弱網(wǎng),網(wǎng)絡(luò)請(qǐng)求回調(diào)需要5秒才行。 用戶(hù)等了2秒,有點(diǎn)不太耐煩,直接把界面關(guān)了。

那么由于回調(diào)沒(méi)有完成,view被強(qiáng)持有,無(wú)法釋放,等到網(wǎng)絡(luò)回調(diào)完成會(huì)發(fā)生
1.內(nèi)存泄漏,沒(méi)有及時(shí)釋放view
2.空指針,如果下面的邏輯沒(méi)有寫(xiě)好,數(shù)據(jù)回來(lái)view不已再。(咋還有絲凄涼)

二、解決內(nèi)存泄漏的思路

第一步:從現(xiàn)象找本質(zhì)

從上述內(nèi)存泄漏的原因來(lái)看,其實(shí)就是Presenter沒(méi)有跟上view的生命周期。我們其實(shí)在view層消失后,即使釋放資源,剪斷引用鏈條就可以解決內(nèi)存泄漏問(wèn)題了。
那么現(xiàn)在的問(wèn)題點(diǎn)空就變成
1.view層什么時(shí)候資源釋放? (找到剪斷時(shí)機(jī))
2.presenter層怎么釋放?(找到剪斷方法)

第二步:通過(guò)Lifecycle來(lái)傳遞生命周期

說(shuō)到這里,我不得不說(shuō)一下。很多人喜歡讓Presenter層也擁有onCreate、onDestroy 等等方法,然后讓view層在自己的生命周期方法時(shí)候去調(diào)用Presenter層的方法。且不說(shuō)Presenter作為一個(gè)業(yè)務(wù)處理層擁有這些方法是否美觀。 就僅僅主動(dòng)調(diào)用這一點(diǎn)其實(shí)就非常的麻煩,可以主動(dòng)調(diào)用,那么就得承擔(dān)“被多次調(diào)用的風(fēng)險(xiǎn)”和“未被調(diào)用的風(fēng)險(xiǎn)”。 在閱讀代碼的時(shí)候,我承認(rèn)我的拳頭硬了。

說(shuō)到Lifecyle就是簡(jiǎn)單的原理就是讓P層去觀察V層的生命周期,當(dāng)V層生命周期發(fā)送改變,便可以監(jiān)聽(tīng)到對(duì)應(yīng)的狀態(tài)。這樣就將顯式調(diào)用變成了隱式監(jiān)聽(tīng)。(這里我就不展開(kāi)說(shuō)了)
1.首先是讓Presenter繼承LifecycleObserver接口
2.view層提供getLifecycle方法,讓Presenter去觀察。

第三步:通過(guò)autodispose來(lái)進(jìn)行網(wǎng)絡(luò)反注冊(cè),剪斷引用鏈

簡(jiǎn)單的講下個(gè)組件的原理:
AutoDispose在內(nèi)部創(chuàng)建了ArchLifecycleObserver,采用Event.ON_ANY注解監(jiān)聽(tīng)Lifecyc的生命周期

當(dāng)Lifecycle發(fā)出ON_DESTROY事件時(shí),ArchLifecycleObserver轉(zhuǎn)發(fā)該事件給特定observer,該observer通過(guò)filter限定Event.ON_DESTROY事件通過(guò)
隨后當(dāng)Activity銷(xiāo)毀時(shí),Lifecycle發(fā)送事件給ArchLifecycleObserver,并調(diào)用onDispose方法取消對(duì)Lifecycle的監(jiān)聽(tīng)。
最后回調(diào)至ObservableCreate在訂閱時(shí)創(chuàng)建的CreateEmitter的dispose方法,將CreateEmitter本身賦值為DISPOSED,銷(xiāo)毀observer實(shí)例.

三、簡(jiǎn)單粗暴,照著抄就完事了

第一步:搭建Mvp的底層抽象類(lèi)

1.通過(guò)底層架構(gòu),把mvp的接口類(lèi)搭建起來(lái)

View層的抽象類(lèi)

interface IBaseView<T : IBasePresenter> {
    fun getPresenter(): T

    fun getLifecycle(): Lifecycle

    /**
     * 判斷Activity、Fragment是否回收
     */
    fun isRecycled(): Boolean
}

Presenter層的抽象類(lèi)

interface IBasePresenter
2.通過(guò)做一個(gè)簡(jiǎn)單的Activity抽象類(lèi)為例
abstract class MvpBaseActivity<T : BasePresenter<*>> : Activity(), IBaseView<T> {
    private lateinit var mPresenter: T

    override fun getLifecycle(): Lifecycle {
        return super.getLifecycle()
    }

    @LayoutRes
    protected abstract fun getLayoutResId(): Int

    protected abstract fun initAll(savedInstanceState: Bundle?)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(getLayoutResId())
        initPresenter()?.let { mPresenter = it }
        initAll(savedInstanceState)
    }


    override fun isRecycled(): Boolean {
        return isFinishing || isDestroyed
    }

    //有的頁(yè)面不需要Mvp所以不去實(shí)現(xiàn)
    open fun initPresenter(): T? {
        return null
    }

    override fun getPresenter(): T {
        if (!::mPresenter.isInitialized) throw IllegalStateException("please override initPresenter()")
        return mPresenter
    }
}
3.做一個(gè)簡(jiǎn)單的Presenter層抽象類(lèi)
abstract class BasePresenter<T : IBaseView<*>>() : IBasePresenter, LifecycleObserver {
    lateinit var view: T
    lateinit var scopeProvider: LifecycleScopeProvider<Lifecycle.Event>

    constructor(view: T) : this() {
        this.view = view
        view.getLifecycle().addObserver(this)
        scopeProvider = AndroidLifecycleScopeProvider.from(view.getLifecycle(), Lifecycle.Event.ON_DESTROY)
        release(view)
    }

    private fun release(view: T) {
        view.getLifecycle().addObserver(object : TempLifecycleObserver() {
            override fun onDestroy() {
                view.getLifecycle().removeObserver(this)
            }
        })
    }
}

這樣 我們就已經(jīng)把生命周期悄悄的傳遞給了presenter,下面是如何簡(jiǎn)單使用(這里網(wǎng)絡(luò)請(qǐng)求以Retrofit網(wǎng)絡(luò)請(qǐng)求為例,不了解retrofit網(wǎng)絡(luò)請(qǐng)求的同學(xué)請(qǐng)坐等我更新,或者去隔壁了解一下)

第二步:使用我們定義好的類(lèi)

1.首先是契約層

class HomeContract {

    interface View : IBaseView<Presenter> {
        fun responseButtonText(isSuccess: Boolean, buttonText:String)
    }


    abstract class Presenter(view: View) : BasePresenter<View>(view) {
        abstract fun requestButtonText()
    }
}

2.下來(lái)是view層

class HomActivity : MvpBaseActivity<HomeContract.Presenter>(), HomeContract.View{
    
    private var demo_tv: TextView? = null

    override fun getLayoutResId(): Int {
        return R.layout.activity_home_live_channel
    }

    override fun initAll(savedInstanceState: Bundle?) {
        initView()
        initData()
    }

    override fun initPresenter(): HomeContract.Presenter? {
        return HomePresenter(this)
    }

    fun initView() {
        demo_tv = findViewById(R.id.demo_tv)
    }

    fun initData() {
        getPresenter().requestButtonText()
    }

    override fun responseButtonText(isSuccess: Boolean,buttonText:String) {
        if(isSuccess){
            demo_tv.text = buttonText;
        }else{
            Toast.makeText(context,"網(wǎng)絡(luò)請(qǐng)求失敗",Toast.LENGTH_LONG)
        }
    }
}

3.接下來(lái)是Presenter層

class HomePresenter(view: HomeContract.View) : HomeContract.Presenter(view) {

    override fun requestButtonText(isRefresh: Boolean, categoryId: String, type: String) {
        RequestManager.getInstance()
                .observableApiService
                .getButtonText()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .autoDisposable(scopeProvider)   //重點(diǎn)是這個(gè)
                .subscribe(object : SingleObserver<BaseResponse<ButtonData>> {
                    override fun onSubscribe(d: Disposable) {}

                    override fun onSuccess(response: BaseResponse<ButtonData>) {
                        if (response.state == 200) {
                            view.responseButtonText(true,response.buttonText)
                        }
                    }

                    override fun onError(e: Throwable) {
                         view.responseButtonText(false,"")
                    }
                })
    }
}

4.網(wǎng)絡(luò)層回調(diào)定義
這里我們?yōu)樯队肧ingle,因?yàn)檫@里只有單次的網(wǎng)絡(luò)請(qǐng)求,如果回調(diào)后無(wú)二次網(wǎng)絡(luò)請(qǐng)求,則使用Single即可

Single<BaseResponse<ButtonData>> getButtonText();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容