美文网首页Android程序员Android开发
Android Jetpack 架构组件之 Lifecycle

Android Jetpack 架构组件之 Lifecycle

作者: Daybreaks | 来源:发表于2020-08-09 13:17 被阅读0次

    Lifecycle的存在意义

    文章开头先来引入一个 业务案例

    这是一个学习英语的App,部分页面支持 划词播放

    如何可以优雅得实现这个真实的业务场景呢?

    首先需要定义一个全局单例的播放器,播放器有一个方法play(val content: String)

    object ContentPlayer {
        
        fun play(content: String) {
            //调用系统播放器播放 
        }
        
        fun prepare(context: Context) {
            //播放器的准备工作
        }
    }
    

    实现ContentPlayer之后,就可以在支持划词播放功能的Activity的划词事件回调中这样写:

    class ContentActivity : AppCompatActivity(), UnderLineWordCallBack {
        
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            ContentPlayer.prepare(this)
        }
        
        //当前Activity的划词播放后回调这里
        override fun callback(content: String) {
            //  开始播放
            ContentPlayer.play(content)
        }
    
    }
    

    这样这个功能就做完了。真得做完了吗?如果你的Leader看到这样的代码,怕不是第二天让你卷铺盖走人~(开玩笑的开玩笑的)

    这样的代码可能会发生 内存泄漏
    假设客户划了一段很长的英语文章,然后点击播放,播放到一半客户不想听了,直接点击了返回键后,播放器还持有着 ContentActivity的引用,在播放器继续播放的过程中,ContentActivity是无法被gc的,这就会出现了问题

    所以我们还需要准备一个unAttach()方法。最终的方案如下:

    object ContentPlayer{
    
        fun play(content: String) {
            //调用系统播放器播放
        }
    
        fun prepare(context: Context) {
            //播放器的准备工作
        }
        
        fun unAttach() {
            //释放当前持有的Activity资源    
        }
    }
    
    class ContentActivity : AppCompatActivity(), UnderLineWordCallBack {
        
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            //准备播放器资源
            ContentPlayer.prepare(this)
        }
        
        //当前Activity的划词播放后回调这里
        override fun callback(content: String) {
            //  开始播放
            ContentPlayer.play(content)
        }
        
        override fun onDestory() {
            ...
            //  释放资源
            ContentPlayer.unAttach()
        }
    
    }
    

    上面这样的代码当然没有问题了,可以正常使用,我们还严谨的保护了App不发生内存泄漏,值得表扬!

    但是还有问题:

    • 无法保证调用一致性,在多人协作开发时存在很大的隐患
    • 调用不够优雅
    • 代码侵入型太强

    如果当前App有很多的Activity要用到划词播放这个功能,那么我们就需要在每一个Activity中重复上面的代码,当代码量上来之后,会很容易遗忘调用unAttach方法,而且一个项目不可能是之后一个人完成,往往是协作开发,如果别人写的界面想要调用你写的ContentPlayer,除非你写了很详细的注释,否则必须深入源码,才知道在Activity的onDestory处去释放资源。

    更优雅,更安全的写法,就是利用Lifecycle组件

    Lifecycle的出现如何解决问题

    在进一步使用Lifecycle优化上述代码之前,先看一下Lifecycle的官方定义:

    生命周期感知型组件可执行操作来响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。这些组件有助于您写出更有条理且往往更精简的代码,这样的代码更易于维护。

    也就是说,我们写代码中开发的某个组件需要去感知生命周期时,要首先想到使用Lifecycle。

    可以让我们在组件内部来监听到生命周期,就像这样:

    object ContentPlayer : LifecycleObserver{
    
        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        fun prepare(context: Context) {
            //播放器的准备工作
        }
        
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun unAttach() {
            //释放当前持有的Activity资源
        }
    }
    

    通过方法注解,决定当前方法被调用的时机。之后在需要使用ContentPlayer的Activity中去注册观察者

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            //  一行代码搞定
            lifecycle.addObserver(ContentPlayer)
        }
    

    用到划词播放的界面只需通过一行代码,lifecycle.addObserver(ContentPlayer)注册lifecycle观察者。完美解决了调用一致性和代码侵入性太强的问题。

    Lifecycle给其他Jectpack相关组件铺路

    Lifecycle除了给我们开发者使用之外,在Android源码很
    Lifecycle组件是Google Jectpack架构的基础,Jectpack的组件:databing、viewmodel等等都依赖于lifecycle对生命周期的感知,所以我认为在学习jectpack和MVVM之前,需要先了解一下Lifecycle的使用和基本实现原理

    相关文章

      网友评论

        本文标题:Android Jetpack 架构组件之 Lifecycle

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