美文网首页
四篇文章带你快速入门Jetpck(上)之Lifecycle,Li

四篇文章带你快速入门Jetpck(上)之Lifecycle,Li

作者: Cache技术分享 | 来源:发表于2021-01-05 06:51 被阅读0次

    四篇文章带你快速入门Jetpck(上)之Lifecycle,LiveData

    Jetpack

    Jetpack 是一个由多个库组成的套件,可帮助开发者遵循最佳做法,减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码,让开发者精力集中编写重要的代码。

    image.png

    官方推荐架构

    img

    请注意,每个组件仅依赖于其下一级的组件。例如,Activity 和 Fragment 仅依赖于视图模型。存储区是唯一依赖于其他多个类的类;在本例中,存储区依赖于持久性数据模型和远程后端数据源。

    Lifecycle

    感知Activity的生命周期并不复杂,但问题在于,在一个Activity中去感知它的生命周期非常简单,而如果要在一个非Activity的类中去感知Activity的生命周期,应该怎么办呢?

    Lifecycles组件就是为了解决这个问题而出现的,它可以让任何一个类都能轻松感知到Activity的生命周期,同时又不需要在Activity中编写大量的逻辑处理。

    UI的生命周期

    activity&fragment生命周期图

    Lifecycles的基本用法

    新建一个MyObserver类,并让它实现LifecycleObserver接口,然后使用方法注解就能感知到Activity的生命周期了:

    class MyObserver : LifecycleObserver {
    
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun activityStart() {
            Log.d("MyObserver", "activityStart")
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun activityStop() {
            Log.d("MyObserver", "activityStop")
        }
    
    }
    

    另外一种方式:实现LifecycleEventObserver接口。

    lifecycle.addObserver(object : LifecycleEventObserver {
                override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                    when (event) {
                        Lifecycle.Event.ON_CREATE -> {
                        }
                        Lifecycle.Event.ON_START -> {
                        }
                        Lifecycle.Event.ON_RESUME -> {
                        }
                        Lifecycle.Event.ON_PAUSE -> {
                        }
                        Lifecycle.Event.ON_STOP -> {
                        }
                        Lifecycle.Event.ON_DESTROY -> {
                        }
                    }
                }
            })
    

    最后,在Activity中调用addObserver()方法来观察LifecycleOwner的生命周期:

    class MainActivity : AppCompatActivity() {
        …
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            …
            lifecycle.addObserver(MyObserver())
        }
        …
    }
    

    Lifecycle状态图

    image.png

    示例

    LifecycleActivity

    class LifecycleActivity : AppCompatActivity() {
    
        private val lifecycleObject = LifecycleObject()
        val TAG = this.javaClass.simpleName
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_lifecycle)
            Log.d(TAG, "onCreate")
            //lifecycleObject.onCreate()
    
            //LifecycleObject1(this)
            LifecycleObject2(this)
        }
    
    //    override fun onResume() {
    //        super.onResume()
    //        lifecycleObject.onResume()
    //        Log.d(TAG, "onResume")
    //    }
    //
    //    override fun onPause() {
    //        super.onPause()
    //        lifecycleObject.onPause()
    //        Log.d(TAG, "onPause")
    //    }
    //
    //    override fun onDestroy() {
    //        super.onDestroy()
    //        lifecycleObject.onDestroy()
    //        Log.d(TAG, "onDestroy")
    //    }
    }
    

    LifecycleObject.kt

    class LifecycleObject {
        val TAG = this.javaClass.simpleName
        private lateinit var player: MediaPlayer
    
        fun onCreate() {
            player = MediaPlayer()
            Log.d(TAG, "onCreate")
        }
    
        fun onResume() {
            thread {
                SystemClock.sleep(3000)
                player.start()
                Log.d(TAG, "onResume")
            }
        }
    
        fun onPause() {
            player.stop()
            Log.d(TAG, "onPause")
        }
    
        fun onDestroy() {
            player.release()
            Log.d(TAG, "onDestroy")
        }
    }
    
    class LifecycleObject1(private val owner: LifecycleOwner) : LifecycleObserver {
        private lateinit var player: MediaPlayer
        val TAG = this.javaClass.simpleName
    
        init {
            owner.lifecycle.addObserver(this)
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        fun onCreate() {
            player = MediaPlayer()
            Log.d(TAG, "onCreate")
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        fun onResume() {
            thread {
                SystemClock.sleep(3000)
                if (owner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
                    player.start()
                    Log.d(TAG, "onResume")
                }
            }
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        fun onPause() {
            player.stop()
            Log.d(TAG, "onPause")
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {
            player.release()
            Log.d(TAG, "onDestroy")
        }
    }
    
    class LifecycleObject2(private val owner: LifecycleOwner) : LifecycleEventObserver {
        private lateinit var player: MediaPlayer
        val TAG = this.javaClass.simpleName
    
        init {
            owner.lifecycle.addObserver(this)
        }
    
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            when (event) {
                Lifecycle.Event.ON_CREATE -> {
                    player = MediaPlayer()
                    Log.d(TAG, "onCreate")
                }
                Lifecycle.Event.ON_START, Lifecycle.Event.ON_RESUME -> {
                    thread {
                        SystemClock.sleep(3000)
                        if (owner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
                            player.start()
                            Log.d(TAG, "onResume")
                        }
                    }
    
                }
                Lifecycle.Event.ON_PAUSE, Lifecycle.Event.ON_STOP -> {
                    player.stop()
                    Log.d(TAG, "onPause")
                }
                Lifecycle.Event.ON_DESTROY -> {
                    player.release()
                    Log.d(TAG, "onDestroy")
                }
                Lifecycle.Event.ON_ANY -> Log.d(TAG, "onAny")
            }
        }
    }
    

    LiveData

    添加依赖库

    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.0-beta01'
    

    简介

    LiveData 是可被观察的数据持有类。具有生命周期(Activity/Fragment/Service)感知的(确保active状态下接受data更新)。

    LiveData是Jetpack提供的一种响应式编程组件,它可以包含任何类型的数据,并在数据发生变化的时候通知给观察者。

    LiveData特别适合与ViewModel结合在一起使用,虽然它也可以单独用在别的地方,但是绝大多数情况下,它都是使用在ViewModel当中的。

    1. 背景 原文

      img

      Android开发中 MVX的开发架构设计,生命周期的感知对于Controller/Presenter/ViewModel不是天然可知。数据资源与泄露的问题。

      MVX的生命周期传递
    2. 2018年 google的AAC(Android Architecture Components)。一套组合的Jetpack组件库,使得ViewModel具有生命周期感知能力。同时也有了数据的感知能力(LiveData)

      img
    • 理解LiveData

      img

      不同于rxjava的观察模式,这里仅通知处于active状态的观察者。

      一旦观察者回复Resume状态,就会收到最新的数据(有利有弊,特殊场景)

    使用LiveData

    LiveData是抽象类

    MutableLiveData

    //声明一个liveData
    val liveA = mutableLiveData<String>()
    //在需要的时候赋值
    liveA.value = "some value of liveA"
    
    //在UI中,观察,在active状态下可以感知变化
    val liveAObserver = Observer<String>{
        value?.let{
            //do something
        }
    }
    liveA.observe(vivewLifeCycleOwner,liveAObserver)
    

    Transformations.map

    //数据的来源多样,赋值于UI需要转换
    liveA.map{
        //转换规则
    }
    
    img

    ==liveData的数据,不会通知inActive的观察者刷新数据,但是当observer恢复Resume的active后,也会得到最新的data==

    img

    MediatorLiveData

    中介者,媒介,将多个liveData的数据,合并处理成一个LiveData

    img

    mediator的liveData可以监听A,B两个数据源的变化,通过addSource后,并响应A/B的变化,转化为mediator的变化。

    • 如果inactive下,A,B都变化,则resume后,也只接受最新的变化

    SwitchMap

    用于数据源的转化,多数据源的切换和控制

    img

    配合mediator的liveData使用,根据条件,选择数据源

    示例

    LiveDataActivity

    class LiveDataActivity : AppCompatActivity() {
        val TAG = this.javaClass.simpleName
    
        // 步骤1
        val testLiveData = MutableLiveData<String>()
    
        //步骤2
        val liveMappedData = testLiveData.map {
            it.hashCode()
        }
    
    
        //步骤3
        val liveData1 = MutableLiveData<Int>()
        val liveData2 = MutableLiveData<Int>()
        val mediatorLive = MediatorLiveData<Pair<String, String>>()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_live_data)
    
            val liveDataFragment = LiveDataFragment()
            supportFragmentManager.beginTransaction()
                .add(R.id.fl_container_live, liveDataFragment)
                .commit()
    
            btn_create_fg_live.setOnClickListener {
                supportFragmentManager.beginTransaction()
                    .attach(liveDataFragment)
                    .commit()
                Log.d(TAG, "onCreate 显示 ${liveDataFragment.isVisible}")
            }
            btn_destroy_fg_live.setOnClickListener {
                supportFragmentManager.beginTransaction()
                    .detach(liveDataFragment)
                    .commit()
                Log.d(TAG, "onCreate 隐藏 ${liveDataFragment.isVisible}")
            }
            btn_change_live.setOnClickListener {
                testLiveData.value = "当前liveData的值为:${(10000..99999).random()}"
            }
            // 步骤1
            testLiveData.observe(this, {
                tv_live_data_activity.text = it
                Log.d(TAG, "LiveData在LiveDataActivity中 $it")
            })
            liveMappedData.observe(this, {
                tv_mapped_data_activity.text = it.toString()
                Log.d(TAG, "LiveData在LiveDataActivity中 map 后 $it")
            })
    
    
            btn_change_live1.setOnClickListener {
                Log.d(TAG, "liveData1 = ${liveData1.value}")
                liveData1.value = (10000..99999).random()
            }
            btn_change_live2.setOnClickListener {
                Log.d(TAG, "liveData2 = ${liveData2.value}")
                liveData2.value = (10000..99999).random()
            }
            mediatorLive.addSource(liveData1) {
                Log.d(TAG, "live1 = $it")
                mediatorLive.value = "live1 = " to it.toString()
            }
            mediatorLive.addSource(liveData2) {
                Log.d(TAG, "live2 = $it")
                mediatorLive.value = "live2 = " to it.toString()
            }
    
        }
    }
    

    activity_live_data.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".fourth.LiveDataActivity">
    
        <TextView
            android:id="@+id/tv_live_data_activity"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="当前liveData的值:"
            android:textColor="#000000"
            android:textSize="20dp"
            tools:text="当前liveData的值:" />
    
        <TextView
            android:id="@+id/tv_mapped_data_activity"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Map后liveData值:"
            android:textColor="#000000"
            android:textSize="20dp"
            tools:text="Map后liveData值:" />
    
    
        <FrameLayout
            android:id="@+id/fl_container_live"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="@color/colorAccent" />
    
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <Button
                android:id="@+id/btn_create_fg_live"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="显示Fragment" />
    
            <Button
                android:id="@+id/btn_destroy_fg_live"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="隐藏Fragment" />
    
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <Button
                android:id="@+id/btn_change_live"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="改变Live值" />
    
            <Button
                android:id="@+id/btn_change_live1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="改变Live1值" />
    
            <Button
                android:id="@+id/btn_change_live2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="改变Live2值" />
    
    
        </LinearLayout>
    </LinearLayout>
    

    LiveDataFragment

    class LiveDataFragment : Fragment() {
        val TAG = this.javaClass.simpleName
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.d(TAG, "onCreate")
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return inflater.inflate(R.layout.fragment_live_data, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            (requireActivity() as LiveDataActivity).apply {
                // 步骤1
                testLiveData.observe(viewLifecycleOwner, {
                    tv_live_fg.text = it
                    Log.i(TAG, "LiveData在LiveDataFragment中 $it")
                    Log.d(TAG, "LiveData在LiveDataFragment中 map 后 ${tv_live_fg.isVisible}")
                })
                // 如果这里用this的话就有问题
                liveMappedData.observe(viewLifecycleOwner, {
                    tv_mapped_live_fg.text = it.toString()
                    Log.d(
                        TAG,
                        "LiveData在LiveDataFragment中 map 后 $it  +   ${tv_mapped_live_fg.isVisible}"
                    )
                })
                mediatorLive.observe(viewLifecycleOwner, {
                    tv_media_live_fg.text = it.toString()
                    Log.d(
                        TAG,
                        "LiveData在LiveDataFragment中 mediatorLive 后 $it  +   ${tv_media_live_fg.isVisible}"
                    )
                })
                // 4
                val swLive = mediatorLive.switchMap {
                    if (it.second.toInt() % 2 == 0) liveData1 else liveData2
                }
                swLive.observe(viewLifecycleOwner, {
                    tv_switch_live_fg.text = it.toString()
                })
            }
            Log.d(TAG, "onViewCreated")
        }
    
        // 步骤1
        override fun onAttach(context: Context) {
            super.onAttach(context)
            Log.d(TAG, "onAttach")
        }
    
        override fun onPause() {
            super.onPause()
            Log.d(TAG, "onPause")
        }
    
        override fun onStop() {
            super.onStop()
            Log.d(TAG, "onStop")
        }
    
        override fun onDestroy() {
            super.onDestroy()
            Log.d(TAG, "onDestroy")
        }
    }
    

    fragment_live_data.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".fourth.LiveDataFragment">
    
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="This is fragment"
            android:textColor="#000000"
            android:textSize="20sp" />
    
        <TextView
            android:id="@+id/tv_live_fg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="tv_live_fg"
            android:textColor="#000000"
            android:textSize="20sp" />
    
        <TextView
            android:id="@+id/tv_mapped_live_fg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="tv_mapped_live_fg1"
            android:textColor="#000000"
            android:textSize="20sp" />
    
        <TextView
            android:id="@+id/tv_media_live_fg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="tv_media_live_fg"
            android:textColor="#000000"
            android:textSize="20sp" />
    
        <TextView
            android:id="@+id/tv_switch_live_fg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
    
            android:textColor="#000000"
            android:textSize="20sp" />
    </LinearLayout>
    

    相关文章

      网友评论

          本文标题:四篇文章带你快速入门Jetpck(上)之Lifecycle,Li

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