Lifecycle、viewLifecycleOwner、LifecycleScope等作用

1,991 阅读5分钟

这是我参与更文挑战的第4天,活动详情查看: 更文挑战

对于刚接触生命周期组件的小伙伴来说,对Lifecycle、LifecycleOwner、ViewLifecycleOwner、LifecycleScope、ViewModelScope、repeatOnLifecycle等这些概念可能会有点分不太清。为便于理解,本文对这几个概念会做初步讲解,暂未涉及深入的实现原理。

一、Lifecycle

在Activity中我们知道有其对应的生命周期如onResume、onDestory,往往我们需要再对应的生命周期里去注册或者反注册一些功能,如果页面多那每个页面都需要添加,当然也可以放到BaseActivty里,但这就约束了我们的Activity必需要继承BaseActivity。

而生命周期感知组件既是可以感知Activty生命周期的变化,既是Activty触发对应的生命周期时,组件里对应的方法就会被触发执行。

1:没有使用生命周期组件

引用官方示例,我们需要在onStart里开启定位服务,onStop里关闭定位,下面是普通写法:

internal class MyLocationListener(
        private val context: Context,
        private val callback: (Location) -> Unit
) {

    fun start() {
        //开启定位服务
    }

    fun stop() {
        //断开定位服务
    }
}

class MyActivity : AppCompatActivity() {
    private lateinit var myLocationListener: MyLocationListener

    override fun onCreate(...) {
        myLocationListener = MyLocationListener(this) { location ->
           //更新UI
        }
    }

    public override fun onStart() {
        super.onStart()
        myLocationListener.start()
    }

    public override fun onStop() {
        super.onStop()
        myLocationListener.stop()
    }
}

这种写法存在的问题:

  1. 如开始提到的,如果较多页面需要开启、关闭,则每个页面都需要写。当然也可以放到BaseActivity中,但这就限制了普通Activty的使用
  2. 这里只提到定位功能需要在onStart、onStop里面处理,实际应用可能会有更多功能在onStart、onStop里面处理,造成onStart、onStop里面代码臃肿,难以维护
  3. 比如onStop里面执行一些释放操作,可能会导致Activty存在的时间比我们实际需要使用的时间更长
  4. 管理不当容易造成内存泄漏

因此引入Lifecycle来解决此类问题,让我们的组件具备生命周期感知功能

2:使用生命周期组件(Lifecycle)

Lifecycle 是一个类,可以理解为观察者的实现类(不过其为抽象类,由其子类如LifecycleRegistry实现),用于存储有关组件(如 activity 或 fragment)的生命周期状态的信息,并允许其他对象观察此状态。如以下示例:

  1. 观察者:MyObserver
  2. 被观察者:MainActivity,通过getLifecycle().addObserver添加观察者

这样被观察者就能够感知Activity的生命周期变化

依赖:

implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1")
class MyObserver(
    private val context: Context,
    private val lifecycle: Lifecycle,
    private val callback: (Location) -> Unit
) : DefaultLifecycleObserver {
    override fun onResume(owner: LifecycleOwner) {
        if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
            //connect
        }
    }

    override fun onPause(owner: LifecycleOwner) {
        //disconnect
    }
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        getLifecycle().addObserver(MyObserver(this@MainActivity,lifecycle)) //生命周期组件添加MyObserver观察者
    }
}

那getLifecycle().addObserver是怎样的呢,可以看LifecycleOwner

二、LifecycleOwner

这里先说下继承关系

LifecycleRegistry extends Lifecycle //观察者实现,其相关的方法,会在Activity、Fragment生命周期方法中被对应调用

Activity implements LifecycleOwner

Fragment implements LifecycleOwner //LifecycleOwner的实现方法getLifecycle()用来提供LifecycleRegistry对象

LifecycleOwner 是一个接口,如Activity、Fragment类里面就会实现该接口,用以提供生命周期组件(提供观察者模式的实现类)。通过getLifecycle()拿到生命周期组件对象,即可通过它添加观察者(示例可以看到LifecycleRegistry这个类里有个addObserver方法,用来添加观察者)

public interface LifecycleOwner {
    Lifecycle getLifecycle();
}


public class LifecycleRegistry extends Lifecycle {
     @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        xxx
    }
}

public class Fragment implements LifecycleOwner,xxx {
    LifecycleRegistry mLifecycleRegistry;
  
    @Override
    @NonNull
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

实现自定义的LifecycleOwner(Fragment 和 Activity 已实现 LifecycleOwner 接口)

如果有一个自定义类并希望使其成为 LifecycleOwner,可以使用 LifecycleRegistry 类,但需要将事件转发到该类


public class LifecycleRegistry extends Lifecycle {
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        xxx
    }
}

class MyActivity : Activity(), LifecycleOwner {

    private lateinit var lifecycleRegistry: LifecycleRegistry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleRegistry = LifecycleRegistry(this)
        lifecycleRegistry.markState(Lifecycle.State.CREATED)
    }

    public override fun onStart() {
        super.onStart()
        lifecycleRegistry.markState(Lifecycle.State.STARTED)
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
}

三、ViewLifecycleOwner

在Fragment里有LifecycleOwner它是针对Activity、Fragment的,而ViewLifecycleOwner如其名,是针对Fragment中View的LifecycleOwner

ViewLifecycleOwner的赋值在onCreateView之前,置空在onDestroyView之后

Fragment中View的生命周期与Fragment本身并不相同,Fragment入back stack的过程会执行onDestroyView但不执行之后的onDestroy与onDetach,而出back stack是从onCreateView开始执行,而没有之前的onAttach与onCreate

class FragmentViewLifecycleOwner implements HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner, ViewModelStoreOwner {

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        initialize();
        return mLifecycleRegistry;
    }        
}

public class Fragment implements LifecycleOwner,xxx {

    lateinit var lifecycleRegistry: LifecycleRegistry
    FragmentViewLifecycleOwner mViewLifecycleOwner;

    @Override
    @NonNull
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

    @MainThread
    @NonNull
    public LifecycleOwner getViewLifecycleOwner() {
        if (mViewLifecycleOwner == null) {
            throw new IllegalStateException("Can't access the Fragment View's LifecycleOwner when "
                    + "getView() is null i.e., before onCreateView() or after onDestroyView()");
        }
        return mViewLifecycleOwner;
    }
}

四、LifecycleScope

LifecycleScope,顾名思义,可以理解为Lifecycle里的协程作用域,每个 Lifecycle 对象都定义了 LifecycleScope,可以指定在特定的生命周期执行协程代码,在Lifecycle 被销毁时取消

你可以通过 lifecycle.coroutineScope 或 lifecycleOwner.lifecycleScope 属性访问 Lifecycle 的 CoroutineScope

implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'

lifecycleScope.launch { 
    withContext(Dispatchers.IO) {
      
    }
}
 
 
lifecycleScope.launch(Dispatchers.IO){

}
 
 
lifecycleScope.launch {
    whenResumed {
   
    }
}
 

lifecycleScope.launchWhenResumed {
  
}

lifecycleScope.launch 
{
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
        
    }
} 

repeatOnLifecycle & lifecycle.whenXxx

lifecycle.launch: 即使处于后台,也一直会执行协程代码,生产者也保持活跃

repeatOnLifecycle: 可以指定在特定的生命周期执行协程协程代码,当不再该状态时就会取消协程块的执行。当程序处于后台时,视图层收集停止,数据生产者停止。

lifecycle.whenXxx: 可以指定在特定的生命周期执行协程协程代码,当不再该状态时就会暂停协程块的执行。当程序处于后台时,视图层收集暂停,数据生产者仍然活跃,可能会在后台持续发出不需要在屏幕上显示的数据项,从而将内存占满。


viewLifecycleOwner.lifecycleScope.launch{} 当应用程序处于后台时不会停止

lifecycleScope.launch {lifecycle.whenResumed {}} 应用程序处于后台时视图层收集暂停,生产者仍活跃,返回时从暂停处继续

lifecycleScope.launch {viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {}} 当应用程序处于后台时视图层收集停止,生产者停止,当它返回时从头开始

State时机
Lifecycle.State.CREATEDonCreate调用后,onStop调用之前
Lifecycle.State.STARTEDonStart调用后, onPause调用之前
Lifecycle.State.RESUMEDonResume调用后

五、ViewModelScope

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'

如果 ViewModel 已清除,则在此范围内启动的协程都会自动取消