美文网首页
Lifecycles

Lifecycles

作者: 阿扎泼柴 | 来源:发表于2018-08-23 16:21 被阅读0次

    本文是对lifecycles原文的学习和翻译。也会加入一些自己的体会。如果你有足够的耐心,就会发现其实没接触之前再难的东西,当你花足够的时间去了解它,你会发现没有什么能难倒你 。附上原文地址:Handling lifecycles with lifecycle-aware components | Android Developers

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

    根据文章标题来看,我们对android各大组件的生命周期都不陌生,但是这里有一个新的概念——生命周期感知组件。这里说白了,就是有这样一个组件如果实现了android.arch.lifecycle提供的接口就能感知如activity/fragment这样的组件的生命周期,当在开发中某个类要依赖生命周期操作就可以这样处理。

    感知生命周期的组件可以执行某个动作,以响应其他组件(activity/fragmrnt)的生命周期状态的变化。这些组件有助于产生更好的组织性和更轻量的代码,也更易于维护。

    现在的开发中,有一种常见的业务需求。比如某一个业务逻辑,要在activity/fragment的某个生命周期中来完成,这样的方式很容易导致代码的错误扩大化以及影响代码可读性。通过使用生命周期感知组件,可以将依赖组件生命周期的代码从生命周期方法中移出来,这样就减少了某些风险,增加代码可读性。

    android.arch.lifecycle提供的类和接口可以让你构建能感知生命周期(lifecycle-aware)的类。所谓可以感知生命周期就是能够感知Activity或者Fragment的生命周期并且可以自行调整类的行为。

    那么在我们工程中怎样来依赖呢,根据自己的需要可以选择你想用的库。

    
    dependencies {   
    def lifecycle_version = "1.1.1"    
    // ViewModel and LiveData    
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"    
    // alternatively - just ViewModel    
    implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" 
    // use -ktx for Kotlin    
    // alternatively - just LiveData    
    implementation "android.arch.lifecycle:livedata:$lifecycle_version"    
    // alternatively - Lifecycles only (no ViewModel or LiveData).   
     //     Support library depends on this lightweight import   
     implementation "android.arch.lifecycle:runtime:$lifecycle_version"   
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" 
    // use kapt for Kotlin   
     // alternately - if using Java8, use the following instead of compiler  
     implementation "android.arch.lifecycle:common-java8:$lifecycle_version"    
    // optional - ReactiveStreams support for LiveData   
     implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"   
     // optional - Test helpers for LiveData   
     testImplementation "android.arch.core:core-testing:$lifecycle_version"
    }
    
    

    这样看起来比较麻烦吧,如果你仅仅是需要 LifecycleLiveDataViewModel只需要这样进行依赖。

    dependencies {
    def lifecycle_version = "1.1.1"
    implementation "android.arch.lifecycle:extensions:$lifecycle_version" 
    implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
    }
    

    当然这么强大的库,肯定是支持kotlin的,kotlin的引用只需要在版本号之前加上-ktx,如下:

    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    

    在Android框架中定义的大多数应用程序组件都有生命周期。生命周期是由操作系统或运行在你的进程中的框架代为管理的。它们是Android工作的核心,你的应用程序必须遵循它们。不这样做可能触发内存泄漏或甚至应用崩溃。
    假如现在我们有一个需求,需要在屏幕上显示你的位置。一个常见的实现方式可能如下:

    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;
        @Override
        public void onCreate(...) {
            myLocationListener = new MyLocationListener(this, (location) -{
                // update UI
            });
        }
        @Override
        public void onStart() {
            super.onStart();
            myLocationListener.start();
            // manage other components that need to respond
            // to the activity lifecycle
        }
        @Override
        public void onStop() {
            super.onStop();
            myLocationListener.stop();
            // manage other components that need to respond
            // to the activity lifecycle
        }
    }
    

    尽管这个示例看起来不错,但是在真正的应用程序中,你最终会在activity的生命周期中有太多的调用,这些调用管理着UI的显示和其他组件。管理多个组件时会在生命周期方法中放置大量代码,例如onStart()和onStop(),这使得它们难以维护。
    此外,不能保证你的需求代码在activity或fragment停止之前启动或者执行完毕。如果需要执行长时间运行的操作,例如onStart()中的某些配置检查,则尤其如此。这可能会导致onStop()方法在onStart()之前完成,从而使组件比需要的时间更长,或者出现严重错误,因为这种本来就是不符合生命周期规律的。

    class MyActivity extends AppCompatActivity {
        private MyLocationListener myLocationListener;
    
        public void onCreate(...) {
            myLocationListener = new MyLocationListener(this, location -> {
                // update UI
            });
        }
    
        @Override
        public void onStart() {
            super.onStart();
            Util.checkUserStatus(result -> {
                // 如果activity结束了,这个方法才被调用,怎么办?
                if (result) {
                    myLocationListener.start();
                }
            });
        }
    
        @Override
        public void onStop() {
            super.onStop();
            myLocationListener.stop();
        }
    }
    

    生命周期包android.arch.lifecycle
    提供类和接口,帮助你以更弹性更独离的方式解决这些问题。


    Lifecycle

    Lifecycle
    是一个保存了关于组件(如activity或fragment)的生命周期状态信息的类,并允许其他对象观察该状态。
    Lifecycle使用两个主要枚举来跟踪其相关组件的生命周期状态:
    Event
    从Lifecycle这个框架和Lifecycle类中分发的生命周期事件。这些事件映射到activity和fragment中的对应生命周期事件中。也就是当activity的生命周期被Lifecycle观察,Lifecycle中对应的生命周期能通过映射拿到activity当前的状态。
    State
    由Lifecycle对象跟踪的组件(activity / fragment)的当前生命周期状态。也就是我们能通过Lifecycle拿到activity/fragment当前的生命周期。


    当然这张图我们不用关心,因为看起来不直观啊。我们来直接看看源码中是什么样子。
     public enum Event {
            /**
             * Constant for onCreate event of the {@link LifecycleOwner}.
             */
            ON_CREATE,
            /**
             * Constant for onStart event of the {@link LifecycleOwner}.
             */
            ON_START,
            /**
             * Constant for onResume event of the {@link LifecycleOwner}.
             */
            ON_RESUME,
            /**
             * Constant for onPause event of the {@link LifecycleOwner}.
             */
            ON_PAUSE,
            /**
             * Constant for onStop event of the {@link LifecycleOwner}.
             */
            ON_STOP,
            /**
             * Constant for onDestroy event of the {@link LifecycleOwner}.
             */
            ON_DESTROY,
            /**
             * An {@link Event Event} constant that can be used to match all events.
             */
            ON_ANY
        }
    
        /**
         * Lifecycle states. You can consider the states as the nodes in a graph and
         * {@link Event}s as the edges between these nodes.
         */
        @SuppressWarnings("WeakerAccess")
        public enum State {
            /**
             * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch
             * any more events. For instance, for an {@link android.app.Activity}, this state is reached
             * <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call.
             */
            DESTROYED,
    
            /**
             * Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is
             * the state when it is constructed but has not received
             * {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet.
             */
            INITIALIZED,
    
            /**
             * Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state
             * is reached in two cases:
             * <ul>
             *     <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;
             *     <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call.
             * </ul>
             */
            CREATED,
    
            /**
             * Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state
             * is reached in two cases:
             * <ul>
             *     <li>after {@link android.app.Activity#onStart() onStart} call;
             *     <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call.
             * </ul>
             */
            STARTED,
    
            /**
             * Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state
             * is reached after {@link android.app.Activity#onResume() onResume} is called.
             */
            RESUMED;
    
            /**
             * Compares if this State is greater or equal to the given {@code state}.
             *
             * @param state State to compare with
             * @return true if this State is greater or equal to the given {@code state}
             */
    

    那我们就来看看具体的使用:
    一个类可以通过向其方法添加注释来监视组件的生命周期状态。然后通过调用Lifecycle类的addObserver()方法添加观察者,如下面的示例所示:

    //通过实现LifecycleObserver,我们就能在自己的类中观察其他组件的生命周期
    public class StudyLifecycle implements LifecycleObserver{
    
    
        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        public void onCreate(){
            Logg.i("onCreate");
        }
    
    
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        public void onStart(){
            Logg.i("onStart");
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        public void onResume(){
            Logg.i("onResume");
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        public void onPause(){
            Logg.i("onPause");
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        public void onStop(){
            Logg.i("onStop");
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        public void onDestroy(){
            Logg.i("onDestroy");
        }
    
    
    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
              //在这里添加我们的观察者
            getLifecycle().addObserver(new StudyLifecycle());
        }
    }
    
    

    通过这个例子可以发现,实际上我们拥有生命周期的组件(activity等)实际上是被作为了被观察者,而Lifecycle作为了观察者。这样通过push的方式,我们就能轻松的了解到组件的周期变化。


    LifecycleOwner

    LifecycleOwner是有单一方法的接口,实现它表示该类具有生命周期。它有一个方法,getLifecycle(),而且是必须由实现的。
    这个接口从单独的类(如fragment和AppCompatActivity)抽象出生命周期的所有权,并允许编写与之一起工作的组件。任何自定义应用程序类都可以实现LifecycleOwner接口。

    实现LifecycleObserver的组件与实现LifecycleOwner的组件无缝地工作。这样你就能看出来实际上我们这这里用的就是观察者模式,实现了LifecycleOwner接口的类作为被观察者,实现了LifecycleObserver接口的类作为观察者。

    对于位置跟踪示例,我们可以使MyLocationListener类实现LifecycleObserver,然后在onCreate()方法中使用activity的Lifecycle初始化它。这允许MyLocationListener类自给自足,这意味着对生命周期状态的更改作出反应的逻辑是在MyLocationListener中完成的,而不是在activity中完成。让各个组件存储它们自己的逻辑使activity和fragment逻辑更易于管理。

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

    这里有一个问题就是,例如当前的activity在onSaveInstanceState方法执行之后在调用其它回调,则会触发崩溃,因此我们永远不会希望调用该回调。
    为了使用变得简单,生命周期类允许其他对象查询当前状态。

    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.getCurrentState().isAtLeast(STARTED)) {
                // connect if not connected
            }
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        void stop() {
            // disconnect if connected
        }
    }
    
    //源码中的解释:
     /**
             * Compares if this State is greater or equal to the given {@code state}.
             *
             * @param state State to compare with
             * @return true if this State is greater or equal to the given {@code state}
             */
            public boolean isAtLeast(@NonNull State state) {
                return compareTo(state) >= 0;
            }
    

    通过这个实现,我们的LocationListener类完全是能感知生命周期的。如果我们需要从另一个activity或fragment中使用我们的LocationListener,我们只需要初始化它。所有的设置和销毁等操作都是由类本身管理的。

    实现自定义的 LifecycleOwner

    这里要说的是,activity/fragment在Support Library 26.1.0以及以后的版本已经实现了LifecycleOwner接口。
    如果您希望生成一个实现 LifecycleOwner
    的自定义类,那么可以使用LifecycleRegistry
    类,但是您需要将事件转发到该类中,如下面的示例代码所示:

    public class MyActivity extends Activity implements LifecycleOwner {
        private LifecycleRegistry mLifecycleRegistry;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mLifecycleRegistry = new LifecycleRegistry(this);
            mLifecycleRegistry.markState(Lifecycle.State.CREATED);
        }
    
        @Override
        public void onStart() {
            super.onStart();
            mLifecycleRegistry.markState(Lifecycle.State.STARTED);
        }
    
        @NonNull
        @Override
        public Lifecycle getLifecycle() {
            return mLifecycleRegistry;
        }
    }
    

    当你去查看activity源码时你会发现,源码也是基于这样实现的。并没有什么变化。

    生命周期感知组件的最佳实践

    • 保持UI控制器(activity/fragment)尽可能简单。它们不应该去直接获取数据;相反,使用ViewModel
      来获取数据,并观察LiveData
      对象以将数据的变化及时反应到UI。
    • 尝试编写数据驱动的UI,其中UI控制器的职责是在数据更改时更新UI,或者将用户操作通知到ViewModel。
    • 将数据的逻辑放在View模型类中。View模型应充当UI控制器和应用程序其余部分之间的连接器。但是要小心,ViewModel的责任不是来获取数据(例如,从一个网络)。相反,ViewModel应该调用适当的组件来获取数据,然后将结果返回到UI控制器。
      也就是说ViewModel只关心获取数据,但是不关心怎么获取的。听起来有一点绕口。打个比方,这里有很多管子,连接到一个大缸,我在一旁一直看着大缸里的水,监测水位的变化。这里的我就相当于UI及时的得到数据的变化,那么这个大缸就是ViewModel,它只关心缸里的水本身,至于水是从哪个管子里来的,不关心。那么管子就相当于另一个概念Repository,它只专注于水从哪里来,也就是数据的获取渠道。

    相关文章

      网友评论

          本文标题:Lifecycles

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