美文网首页
Android架构设计-简单粗暴,搞定MVP网络请求内存泄漏

Android架构设计-简单粗暴,搞定MVP网络请求内存泄漏

作者: 叶满林 | 来源:发表于2021-07-20 15:41 被阅读0次

    一、使用Mvp为什么怎么开始内存内存泄漏了?

    我们先简单的看一段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)
                        }
                    }
                }
            })
        }
    }
    

    大体上这段代码是完成一个单次的网络请求,然后进行回调的过程,那么网络操作是一个耗时操作,我们不知道请求什么时候可以回来。

    场景模拟:比如说现在是一个弱网,网络请求回调需要5秒才行。 用户等了2秒,有点不太耐烦,直接把界面关了。

    那么由于回调没有完成,view被强持有,无法释放,等到网络回调完成会发生
    1.内存泄漏,没有及时释放view
    2.空指针,如果下面的逻辑没有写好,数据回来view不已再。(咋还有丝凄凉)

    二、解决内存泄漏的思路

    第一步:从现象找本质

    从上述内存泄漏的原因来看,其实就是Presenter没有跟上view的生命周期。我们其实在view层消失后,即使释放资源,剪断引用链条就可以解决内存泄漏问题了。
    那么现在的问题点空就变成
    1.view层什么时候资源释放? (找到剪断时机)
    2.presenter层怎么释放?(找到剪断方法)

    第二步:通过Lifecycle来传递生命周期

    说到这里,我不得不说一下。很多人喜欢让Presenter层也拥有onCreate、onDestroy 等等方法,然后让view层在自己的生命周期方法时候去调用Presenter层的方法。且不说Presenter作为一个业务处理层拥有这些方法是否美观。 就仅仅主动调用这一点其实就非常的麻烦,可以主动调用,那么就得承担“被多次调用的风险”和“未被调用的风险”。 在阅读代码的时候,我承认我的拳头硬了

    说到Lifecyle就是简单的原理就是让P层去观察V层的生命周期,当V层生命周期发送改变,便可以监听到对应的状态。这样就将显式调用变成了隐式监听。(这里我就不展开说了)
    1.首先是让Presenter继承LifecycleObserver接口
    2.view层提供getLifecycle方法,让Presenter去观察。

    第三步:通过autodispose来进行网络反注册,剪断引用链

    简单的讲下个组件的原理:
    AutoDispose在内部创建了ArchLifecycleObserver,采用Event.ON_ANY注解监听Lifecyc的生命周期

    当Lifecycle发出ON_DESTROY事件时,ArchLifecycleObserver转发该事件给特定observer,该observer通过filter限定Event.ON_DESTROY事件通过
    随后当Activity销毁时,Lifecycle发送事件给ArchLifecycleObserver,并调用onDispose方法取消对Lifecycle的监听。
    最后回调至ObservableCreate在订阅时创建的CreateEmitter的dispose方法,将CreateEmitter本身赋值为DISPOSED,销毁observer实例.

    三、简单粗暴,照着抄就完事了

    第一步:搭建Mvp的底层抽象类

    1.通过底层架构,把mvp的接口类搭建起来

    View层的抽象类

    interface IBaseView<T : IBasePresenter> {
        fun getPresenter(): T
    
        fun getLifecycle(): Lifecycle
    
        /**
         * 判断Activity、Fragment是否回收
         */
        fun isRecycled(): Boolean
    }
    

    Presenter层的抽象类

    interface IBasePresenter
    
    2.通过做一个简单的Activity抽象类为例
    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
        }
    
        //有的页面不需要Mvp所以不去实现
        open fun initPresenter(): T? {
            return null
        }
    
        override fun getPresenter(): T {
            if (!::mPresenter.isInitialized) throw IllegalStateException("please override initPresenter()")
            return mPresenter
        }
    }
    
    3.做一个简单的Presenter层抽象类
    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)
                }
            })
        }
    }
    

    这样 我们就已经把生命周期悄悄的传递给了presenter,下面是如何简单使用(这里网络请求以Retrofit网络请求为例,不了解retrofit网络请求的同学请坐等我更新,或者去隔壁了解一下)

    第二步:使用我们定义好的类

    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.下来是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,"网络请求失败",Toast.LENGTH_LONG)
            }
        }
    }
    

    3.接下来是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)   //重点是这个
                    .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.网络层回调定义
    这里我们为啥用Single,因为这里只有单次的网络请求,如果回调后无二次网络请求,则使用Single即可

    Single<BaseResponse<ButtonData>> getButtonText();
    

    相关文章

      网友评论

          本文标题:Android架构设计-简单粗暴,搞定MVP网络请求内存泄漏

          本文链接:https://www.haomeiwen.com/subject/axqrmltx.html