操作Lifecycle

来源:互联网 发布:机器人算法工程师 编辑:程序博客网 时间:2024/06/06 09:59

android.arch.lifecycle包提供了类和接口让开发者用来创建兼顾生命周期的组件,也就是说这些组件会自动根据当前Activity或Fragment的生命周期来调整行为。如果没有配合生命周期进行资源的获取和释放,可能导致内存泄露甚至是闪退。

位置监听的实现一般是下面这样子的:

class MyLocationListener {    public MyLocationListener(Context context, Callback callback) {        // ...    }    void start() {        // connect to system location service    }    void stop() {        // disconnect from system location service    }}class MyActivity extends AppCompatActivity {    private MyLocationListener myLocationListener;    public void onCreate(...) {        myLocationListener = new MyLocationListener(this, (location) -> {            // update UI        });  }    public void onStart() {        super.onStart();        myLocationListener.start();    }    public void onStop() {        super.onStop();        myLocationListener.stop();    }}

这样做有两个缺点。
一个是要去重写生命周期回调的方法,如果有多种监听,生命周期回调的方法就会变得很复杂。
第二个是尽管监听方法是写在回调当中的,但是方法的实际执行顺序并不一定按照这个顺序,比如onStart()中注册监听前可能需要进行一系列判断,但是可能onStop()在判断完成之前已经调用了,也就是移除监听之后才会去注册监听。这种情况下就会导致内存泄露。

这个时候Lifecycle这个类就很好地帮我们解决了这个问题。

Lifecycle

Lifecycle类中保存了应用组件(比如Activity或者Fragment)的生命周期状态,并且让其他对象可以观察到具体状态。
Lifecycle使用两个主要的枚举类来跟踪绑定的系统组件的状态。

  • Event:系统和Lifecycle类所分发的生命周期事件,映射到Activity和Fragment中即是各个生命周期回调。
  • State:所绑定系统组件的当前状态。

下图就展示了Event和State:
这里写图片描述

一个类可以通过给方法添加注解的方式来监听组件的生命周期状态。

public class MyObserver implements LifecycleObserver {    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)    public void onResume() {    }    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)    public void onPause() {    }}aLifecycleOwner.getLifecycle().addObserver(new MyObserver());

LifecycleOwner

LifecycleOwner是一个只有单个方法的接口,只包含子类必须实现的getLifecycle()方法。

This class abstracts the ownership of a Lifecycle from individual classes (for example, activities and fragments) and allows writing components that can work with both of them. Any custom application class can implement the LifecycleOwner interface.
这个类把Activity或者Fragment中生命周期的所有权抽象出来,并且可以创建可以和这两者一起配合的组件。任何自定义的application类都可以实现这个接口。

在Architecture库正式发布之前,support库的Fragment和AppcompatActivity还没有实现这个接口,正式发布之后才会去实现。正式发布之前暂时使用LifecycleActivity和LifecycleFragment。

所以开篇的例子就可以优化为Activity继承于LifecycleActivity,MyLocationListener作为一个LifecycleObserver使用Lifecycle实例化,这样MyLocationListener就可以自动释放资源了。

class MyActivity extends LifecycleActivity {    private MyLocationListener myLocationListener;    public void onCreate(...) {        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {            // update UI        });        Util.checkUserStatus(result -> {            if (result) {                myLocationListener.enable();            }        });  }}

另一个使用场景就是需要获取当前生命周期的阶段,以判断进行某项操作是否合适,以免导致闪退等问题。此时可以调用Lifecycle类的方法查询阶段:

class MyLocationListener implements LifecycleObserver {    private boolean enabled = false;    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {       ...    }    @OnLifecycleEvent(Lifecycle.Event.ON_START)    void start() {        if (enabled) {           // connect        }    }    public void enable() {        enabled = true;        if (lifecycle.getState().isAtLeast(STARTED)) {            // connect if not connected        }    }    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)    void stop() {        // disconnect if connected    }}

这样一实现,LocationListener这个类就完全兼顾到了生命周期,可以自己进行初始化和清除回收,不用交给Activity来管理。如果我们还要在其他Activity或者Fragment中使用这个LocationListener,只要初始化就可以了,后续的操作LocationListener自己会处理。

可以配合Lifecycle类一起使用的类就叫做Lifecycle-aware component。推荐那些提供需要搭配Android生命周期进行使用的类的第三方库提供这种Lifecycle-aware组件,这样使用方就可以很方便地集成进去,节省掉很多处理生命周期的问题。

比如LiveData就是这样一个组件。LiveData搭配ViewModel进行使用就可以在兼顾Android生命周期的前提下比较轻松地提供数据。

Lifecycle最佳实践

  • UI控制器(Activity和Fragment)应该尽可能简洁 ,应该把获取数据的工作交给ViewModel去完成,然后监听LiveData来更新界面。
  • UI控制器的作用应该是在数据改变时更新数据,或者把用户操作反馈给ViewModel。
  • 把数据逻辑放到ViewModel当中。ViewModel应该作为UI控制器和应用其他部分交互的中间者。需要注意的是,ViewModel的职责不是获取数据,而是调用其他组件来完成这件事,然后把结果返回给UI控制器。
  • 使用DataBinding在UI控制器和View之间保持一个清爽的结构,View会更有说明性,也会减少Activity和Fragment中使用的更新UI的代码。如果不想用DataBinding,也可以使用ButterKnife之类的库。
  • 如果UI太过复杂,可以考虑创建一个Presenter来修改UI。
  • 绝对不要在ViewModel中引用View或者Activity的context,如果configuration发生改变就会导致内存泄露。

自定义实现LifecycleOwner

可以不用继承于LifecycleActivity或者LifecycleFragment,直接实现LifecycleRegisteryOwner接口把任意Activity或者Fragment变成一个LifecyleOwner:

public class MyFragment extends Fragment implements LifecycleRegistryOwner {    LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);    @Override    public LifecycleRegistry getLifecycle() {        return lifecycleRegistry;    }}

如果是某个自定义类要成为LifecycleOwner,同样也是实现LifecycleRegistryOwner接口,只不过要自己把事件转发到这个类当中,如果是Activity和Fragment是会自动转发的。

原创粉丝点击