欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 架构组件之 LifeCycle详解

程序员文章站 2022-03-03 21:31:37
使用生命周期感知型组件处理生命周期生命周期感知型组件可执行操作来响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。这些组件有助于您写出更有条理且往往更精简的代码,这样的代码更易于维护。一种常见的模式是在 Activity 和 Fragment 的生命周期方法中实现依赖组件的操作。但是,这种模式会导致代码条理性很差而且会扩散错误。通过使用生命周期感知型组件,您可以将依赖组件的代码从生命周期方法移入组件本身中。androidx.lifecycle 软件包提供了可用于构建生命...

使用生命周期感知型组件处理生命周期

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

一种常见的模式是在 Activity 和 Fragment 的生命周期方法中实现依赖组件的操作。但是,这种模式会导致代码条理性很差而且会扩散错误。通过使用生命周期感知型组件,您可以将依赖组件的代码从生命周期方法移入组件本身中。

androidx.lifecycle 软件包提供了可用于构建生命周期感知型组件的类和接口 - 这些组件可以根据 Activity 或 Fragment 的当前生命周期状态自动调整其行为。

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

        fun start() {
            // connect to system location service
        }

        fun stop() {
            // disconnect from system location service
        }
    }

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

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

        public override fun onStart() {
            super.onStart()
            myLocationListener.start()
            // manage other components that need to respond
            // to the activity lifecycle
        }

        public override fun onStop() {
            super.onStop()
            myLocationListener.stop()
            // manage other components that need to respond
            // to the activity lifecycle
        }
    }
    

虽然此示例看起来没问题,但在真实的应用中,最终会有太多管理界面和其他组件的调用,以响应生命周期的当前状态。管理多个组件会在生命周期方法(如 onStart() 和 onStop())中放置大量的代码,这使得它们难以维护。

此外,无法保证组件会在 Activity 或 Fragment 停止之前启动。在我们需要执行长时间运行的操作(如 onStart() 中的某种配置检查)时尤其如此。这可能会导致出现一种竞争条件,在这种条件下,onStop() 方法会在 onStart() 之前结束,这使得组件留存的时间比所需的时间要长。

类和接口

  • Lifecycle
    Lifecycle是一个持有组件生命周期状态(如Activity或Fragment)的信息的类,并允许其他对象观察此状态。
  • Event :从框架和Lifecycle类派发的生命周期事件。这些事件映射到活动和片段中的回调事件。
  • State :由Lifecycle对象跟踪的组件的当前状态。
    Android 架构组件之 LifeCycle详解
    您可以将状态看作图中的节点,将事件看作这些节点之间的边。

类可以通过向其方法添加注解来监控组件的生命周期状态。然后,您可以通过调用 Lifecycle 类的 addObserver() 方法并传递观察者的实例来添加观察者,

    class MyObserver : LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        fun connectListener() {
            ...
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        fun disconnectListener() {
            ...
        }
    }

    myLifecycleOwner.getLifecycle().addObserver(MyObserver())
    
  • LifecycleOwner (重要)Lifecycle持有者
  1. LifecycleOwner 是单一方法接口,表示类具有 Lifecycle。它具有一种方法(即 getLifecycle()),该方法必须由类实现。如果您尝试管理整个应用进程的生命周期,使用 ProcessLifecycleOwner。
  2. 此接口从各个类(如 Fragment 和 AppCompatActivity)抽象化 Lifecycle 的所有权,并允许编写与这些类搭配使用的组件。任何自定义应用类均可实现 LifecycleOwner 接口。
  3. 实现 LifecycleObserver 的组件可与实现 LifecycleOwner 的组件无缝协同工作,因为所有者可以提供生命周期,而观察者可以注册以观察生命周期。
  4. 对于位置跟踪示例,我们可以让 MyLocationListener 类实现 LifecycleObserver,然后在 onCreate() 方法中使用 Activity 的 Lifecycle 对其进行初始化。这样,MyLocationListener 类便可以“自给自足”,这意味着,对生命周期状态的变化做出响应的逻辑会在 MyLocationListener(而不是在 Activity)中进行声明。让各个组件存储自己的逻辑,可使 Activity 和 Fragment 逻辑更易于管理
  5. class MyActivity : AppCompatActivity() {
        private lateinit var myLocationListener: MyLocationListener
        override fun onCreate(...) {
            myLocationListener = MyLocationListener(this, lifecycle) { location ->
                // update UI
            }
            Util.checkUserStatus { result ->
                if (result) {
                    myLocationListener.enable()
                }
            }
        }
    } 
    
    

一个常见的用例是,如果 Lifecycle 现在未处于良好的状态,则应避免调用某些回调。例如,如果回调在 Activity 状态保存后运行 Fragment 事务,就会引发崩溃,因此我们绝不能调用该回调。
为简化此用例,Lifecycle 类允许其他对象查询当前状态。

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

        private var enabled = false

        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun start() {
            if (enabled) {
                // connect
            }
        }

        fun enable() {
            enabled = true
            if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
                // connect if not connected
            }
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun stop() {
            // disconnect if connected
        }
    }

实现自定义 LifecycleOwner
Support Library 26.1.0 及更高版本中的 Fragment 和 Activity 已实现 LifecycleOwner 接口。官方说已经实现了接口,但是我没看到啊。

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

    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
        }
    }
    
  • LifecycleObserver(生命周期观察者接口)
    LifecycleObserver 是一个观察者接口,实现了它,可以通过注解或者继承的方式,来管理声明周期的监听。只要在持有lifecycle的类中注册了它,当声明周期发生变化时,它就能收到,进行我们自定义的操作。
    两种实现方式:
  1. 实现DefultLifecyceObserver接口,然后重写里面生命周期方法;
  2. 直接实现LifecycleObserver接口,然后通过注解的方式来接收生命周期的变化;
    Lifecycle.java文档中是建议使用第一种方式,因为文档中说明了,随着Java8成为主流,注解的方式会被弃用。DefaultLifecycleObserver是需要另外声明的java8 比如下面
    GenericLifecycleObserver,FullLifecycleObserver,DefaultLifecycleObserver 这三个接口都是直接或者间接继承的LifecycleObserver

Lifecycle的使用

两个简单的Activity,FirstActivity 和SecondActivity, 单纯的一个跳转

public class FirstActivity extends AppCompatActivity {

    private Button firstBtn;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_activity_layout);
        initView();
        initListener();
    }

    private void initView() {
        firstBtn = findViewById(R.id.first_btn);
    }

    private void initListener() {
        firstBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}

们要做的是要写一个需要拥有声明周期的类,正常我们自定义控件啊,或者做其他逻辑的类,是没有声明周期的,现在有了LifecycleObserver,我们可以让一个普通的类拥有感知声明周期变化的能力。比如,现在自定义一个,MyObserver类。

public class MyObserver implements DefaultLifecycleObserver{
   private static final String TAG = "MyListener";

    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onCreate()");
        Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onStart()");
        Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onResume()");
        Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());

    }

    @Override
    public void onPause(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onPause()");
        Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onStop()");
        Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onDestroy() ");
        Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());
    }

}

直接继承DefaultLifecycleObserver接口,来实现它所有的方法。我们在里面做了log,来查看,是否这个类,收到了activity声明周期的变化。
然后,要做的就是注册监听
在Activity 的OnCreate方法中,调用getLifecycle();

public class FirstActivity extends AppCompatActivity {

    private Button firstBtn;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_activity_layout);
        initView();
        initListener();
        //添加了这一行代码
        getLifecycle().addObserver(new MyObserver());
    }

    private void initView() {
        firstBtn = findViewById(R.id.first_btn);
    }

    private void initListener() {
        firstBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}

Activity中可以直接 getLifecycle().addObserver(new MyObserver()); 这样,就已经注册了声明周期观察者的监听。运行查看log
启动FirstActivity后,MyObserver类已经监听到了Activity的声明周期方法

要注意的是:
生命周期状态为RESUMED时表示,当前activity 是在前台,并且可交互也就是onResume()执行后

生命周期状态为STARTED时,表示当前activity处于可见但是不可交互,也就是onStart()方法刚执行完或者onPause()方法刚执行完的状态

生命周期状态为CREATED,表示onCreate()方法刚刚执行完或者onStop()方法刚刚执行完,也就是当前activity不在前台,但是也没有处于销毁状态。

生命周期状态为DESTORYED,表示当前Activity还不存在,没有被创建或者已经销毁,我们通常考虑比较多的就是,onDestory()方法执行后,当前Activity已经销毁。

所以,如果我们要保证在Activity或者Fragment的有效生命周期内进行的操作,必须判断,当前lifecycle的状态是否至少是CREATED状态,避免Activity或者fragment销毁了以后,回调或者网络请求才回来,此时做一些操作会导致异常。

添加以下代码,就是我们把lifecycle对象传给观察者,让它自己去判断回调后的代码,保证至少是CREATED状态

private Lifecycle lifecycle;
   public MyObserver(Lifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }
//然后再相应的回调方法中使用下面代码判断,保证数据回调回来,当前activity是存在的
    if (lifecycle.getCurrentState().isAtLeast(CREATED)) {
            //这里只是示例,不一定是CREATED
    }

生命周期感知型组件的最佳做法

  • 尽可能保持您的UI控制器(活动和片段)尽可能精简。他们不应该试图获取他们自己的数据;相反,使用ViewModel来做到这一点,并观察一个LiveData对象来反映更改回视图。
  • 尝试编写数据驱动的用户界面,其中您的用户界面控制器的职责是在数据更改时更新视图,或将用户操作通知给ViewModel。
  • 把你的数据逻辑放在ViewModel类中。ViewModel应作为您的UI控制器和其他应用程序之间的连接器。但要小心,ViewModel不负责提取数据(例如,来自网络)。相反,ViewModel应调用相应的组件来获取数据,然后将结果提供给UI控制器。
  • 使用dataBinding在视图和UI控制器之间保持干净的界面。这使您可以使您的视图更具说明性,并最大限度地减少需要在活动和片段中编写的更新代码。

本文地址:https://blog.csdn.net/lin_henry/article/details/108150227

相关标签: Android