美文网首页Android Jetpack
Android Jetpack 应用指南(四) - Lifecy

Android Jetpack 应用指南(四) - Lifecy

作者: 林栩link | 来源:发表于2021-06-20 22:12 被阅读0次

    Lifecycle诞生的背景

    在 Android 应用程序的开发过程,我们会经常遇到这样一个需求,一个第三方或系统组件需要在Activity/Fragment的onCreate()方法中初始化,在onPause()方法中停止组件,在onDestroy()中对组件进行资源回收。这样的工作非常繁琐,会让组件与页面的耦合度增高,但是这些繁琐的工作却又不得不做,否则可能会造成内存泄露。
    我们希望我们对自定义的组件的管理,不依赖与页面的生命周期的回调方法,同时,在页面的生命周期发生变化时,也能及时收到通知。为此Google提供了Lifecycle作为解决方案。

    什么是Lifecycle

    Lifecycle 可以用于构建生命周期感知型组件,这些组件可以根据 Activity 或 Fragment 的当前生命周期状态调整行为。

    Lifecycle的作用与意义

    Lifecycle可以帮助开发者创建可感知生命周期的组件。这样,组件就可以在其内部管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄露的发生
    需要注意的是,LifeCycle不仅只对Activity/Fragment有用,在Service和Application中同样可以使用。

    Lifecycle使用示例

    使用Lifecycle监听Activity/Fragment的生命周期

    接下来我们以一个案例来演示Lifecycle是如何使用的。
    假设有这样一个常见的需求:在用户打开某个页面时,获取用户当前的地理位置。用户离开该页面后,则停止获取用户地理位置。面对这样的需求,我们通常会这么写

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 初始化任务管理器
            initLocationManager();
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            // 获取用户位置
            getUserLocation();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            // 停止获取用户位置
            stopGetLocation();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 释放任务管理器
            releaseLocationManager();
        }
    }
    

    从上述代码可以看出,获取地理位置这个需求的实现,和页面的生命周期息息相关。如果我们希望将获得地理位置这一功能独立成一个组件,那么我们不得不在页面生命周期各个回调方法中,对组件进行通知,只有这样组件才能感知到页面的生命周期变化(有经验的开发一定会注意到,这就是早期MVP架构中Presenter感知页面生命周期的做法)。
    面对这个问题,接下来我们就来看看,LifeCycle是如何处理的。
    在使用 Lifecycle 之前我们需要在应用或模块的build.gradle中添加lifecycle的依赖项

    lifecycle-extensions 目前已经弃用。Google为我们提供了,可供自由选择的lifecycle组件

    dependencies {
        def lifecycle_version = "2.3.1"
      
        // Lifecycles only (without ViewModel or LiveData)
        implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
      
    }
    

    我们为位置管理器定义一个类LocationObserver的类,LocationObserver需要实现LifecycleObserver接口。如果我们需要得知页面的生命周期,只需要定义一个@OnLifecycleEvent(Lifecycle.Event.ON_XXX)标签即可,当页面的生命周期发生变化时,这些被标识的方法会自定被调用。如下所示:

    //1. 自定义的LifecycleObserver观察者,用注解声明每个方法观察的宿主的状态
    class LocationObserver extends LifecycleObserver{
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        void onStart(@NotNull LifecycleOwner owner){
          //开启定位
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        void onStop(@NotNull LifecycleOwner owner){
           //停止定位
        }
    }
    
    

    在Activity/Fragment中引用LocationObserver,并同过getLifecycle().addObserver(observer)方法将观察者与被观察者绑定起来,这样LocationObserver就能感知到Activity/Fragment的生命周期变化。如下所示:

    //2. 注册观察者,观察宿主生命周期状态变化
    class MyActivity extends AppCompactActivity{
      public void onCreate(Bundle bundle){
        
        MyLifecycleObserver observer =new MyLifecycleObserver();
        getLifecycle().addObserver(observer);
        
      }
    }
    
    //2. 注册观察者,观察宿主生命周期状态变化
    class MyFragment extends Fragment{
      public void onCreate(Bundle bundle){
        
        MyLifecycleObserver observer =new MyLifecycleObserver();
        getLifecycle().addObserver(observer);
        
      }
    }
    

    除了继承LifecycleObserver运用注解的形式来实现宿主生命周期的监听,Lifecycle组件中还提供了LifecycleEventObserver来监听宿主的生命周期。

      public class LocationObserver implements LifecycleEventObserver {
    
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                                   @NonNull Lifecycle.Event event) {
            //需要自行判断event是onstart, 还是onstop
        }
    }
    

    如果你的项目使用了Java8,那么你还可以使用DefaultLifecycleObserver来监听宿主的生命周期。
    使用DefaultLifecycleObserver之前,你还需要在build.gradle中额外引入以下依赖

    dependencies {
        def lifecycle_version = "2.3.1"
      ...//省略其它依赖
      implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
    }
    

    然后实现DefaultLifecycleObserver接口,根据需要实现里面的方法即可。

    public class LocationObserver implements DefaultLifecycleObserver {
    
        @Override
        public void onCreate(@NonNull LifecycleOwner owner) {
    
        }
    
        @Override
        public void onStart(@NonNull LifecycleOwner owner) {
    
        }
    
        @Override
        public void onResume(@NonNull LifecycleOwner owner) {
    
        }
    
        @Override
        public void onPause(@NonNull LifecycleOwner owner) {
    
        }
    
        @Override
        public void onStop(@NonNull LifecycleOwner owner) {
    
        }
    
        @Override
        public void onDestroy(@NonNull LifecycleOwner owner) {
    
        }
    }
    

    需要额外注意的是,如果你正在使用Java8,那么首先应该考虑的选择是使用DefaultLifecycleObserver而不是LifecycleObserver

    • 如果业务类同时实现DefaultLifecycleObserverLifecycleEventoServer,则将首先调用DefaultLifecycleObserver的方法,然后再调用LifecycleEventoServer.onStateChanged(LifecycleOwner,Lifecycle.Event)
    • 如果一个类实现了DefaultLifecycleObserver,又同时使用了OnLifecycleEvent注解,那么注解方法将被忽略。

    使用Lifecycle监听Service的生命周期

    在上面我们介绍了如何在组件中监听Activity/Fragment的生命周期,在Android中Service同样是一个拥有生命周期的重要组件。

    为了便于对Service生命周期的监听,达到解耦Service与组件的目的,Google提供了一个LifecycleService的类。该类继承自Service,并实现了LifeCycleOwner接口,与Activity/Fragment类似,它也提供了一个名为getLifeCycle()的方法供我们使用,除此以外,它与普通的Service使用起来并无差别。LifecycleService的源码如下:

    public class LifecycleService extends Service implements LifecycleOwner {
    
        private final ServiceLifecycleDispatcher mDispatcher = new ServiceLifecycleDispatcher(this);
    
        @CallSuper
        @Override
        public void onCreate() {
            mDispatcher.onServicePreSuperOnCreate();
            super.onCreate();
        }
    
        @CallSuper
        @Nullable
        @Override
        public IBinder onBind(@NonNull Intent intent) {
            mDispatcher.onServicePreSuperOnBind();
            return null;
        }
    
        @SuppressWarnings("deprecation")
        @CallSuper
        @Override
        public void onStart(@Nullable Intent intent, int startId) {
            mDispatcher.onServicePreSuperOnStart();
            super.onStart(intent, startId);
        }
    
        // this method is added only to annotate it with @CallSuper.
        // In usual service super.onStartCommand is no-op, but in LifecycleService
        // it results in mDispatcher.onServicePreSuperOnStart() call, because
        // super.onStartCommand calls onStart().
        @CallSuper
        @Override
        public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            return super.onStartCommand(intent, flags, startId);
        }
    
        @CallSuper
        @Override
        public void onDestroy() {
            mDispatcher.onServicePreSuperOnDestroy();
            super.onDestroy();
        }
    
        @Override
        @NonNull
        public Lifecycle getLifecycle() {
            return mDispatcher.getLifecycle();
        }
    }
    

    Android原生的Service因为并未实现LifecycleOwner接口,所以LiveData等需要感知生命周期组件,就无法在Service中使用。为了解决这个问题,Android中提供了一个支持Lifecycle功能的LifecycleService
    1.在 Service 中使用 Lifecycle 首先需要在build.gradle中添加相关依赖

    dependencies {
        def lifecycle_version = "2.3.1"
        
        // optional - helpers for implementing LifecycleOwner in a Service
        implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
    
    }
    

    2.添加相应的依赖之后,我们在创建Service时需要让它继承LifecycleService,LifecycleService是Service的子类,它在Service的基础上实现了LifecyclerOwner接口,并提供getLifecycle()方法以便我们使用。除此以外,它与普通的Service使用起来并无差别。

    public class MainService extends LifecycleService {
    
        public MyLifecycleObserver observer;
        
        public MainService() {
            observer = new MyLifecycleObserver();
            getLifecycle().addObserver(observer);
        }
    }
    

    使用Lifecycle监听Application的生命周期

    具有生命周期的系统组件,除了Activity、Fragment和Service外,还有Application。很多时候,我们会遇到这样的需求:我们想知道应用程序当前是前台还是后台,或者当应用程序从后台回到前台时,我们能够得到通知。以前也有不少方案能实现,但是大多比较繁琐,现在利用Lifecycle组件中的ProcessLifecycleOwner,可以非常轻松的监控整个应用程序的生命周期。
    1.监听 Application 的生命周期,首先需要在build.gradle中添加相关依赖

    dependencies {
        def lifecycle_version = "2.3.1"
        
        // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
        implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
    
    }
    

    2.然后,定义一个AppLifecycle的类,该类实现LifecycleObserver接口,负责监控整个应用程序的生命周期。

    public class AppLifecycle implements LifecycleObserver {
    
            @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
            public void onAppCreate() {
                // 在应用的生命周期内,只会被回调一次
            }
    
            @OnLifecycleEvent(Lifecycle.Event.ON_START)
            public void onAppStart() {
                // 当应用在前台出现时被回调
            }
            
            @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
            public void onAppResume() {
               // 当应用在前台出现时被回调
            }
    
            @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
            public void onAppPause() {
               // 当应用退出到后台时被回调
            }
            
            @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
            public void onAppStop() {
               // 当应用退出到后台时被回调
            }
            
            @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
            public void onAppDestroy() {
               // 永远不会被调用,系统不会分发ON_DESTROY事件
            }
        }
    

    需要注意的是,监控应用程序生命周期的时候,Lifecycle.Event.ON_CREATE只会被回调一次,Lifecycle.Event.ON_DESTROY则永远不会被回调。
    3.接下来在Application中使用ProcessLifecycleOwner.get().getLifecycle().addObserver()方法添加观察者,示例如下:

    public class AbsApplication extends Application {
    
        @Override
        public void onCreate() {
            ProcessLifecycleOwner.get().getLifecycle().addObserver(new AppLifecycle());
            super.onCreate();
        }
    }
    

    实际上监听整个应用生命周期并不需要在Application中添加观察者,我们可以在任意合适的地方调用 ProcessLifecycleOwner.get().getLifecycle().addObserver(new AppLifecycle()),但是,如果你需要监听Lifecycle.Event.ON_CREATE事件,就必须在Application生命周期进入OnCreate()之前完成观察者的添加。

    Lifecycle原理解析

    Fragment是如何实现Lifecycle的

    Fragemnt中关于Lifecycle的核心代码如下

    public class Fragment implements LifecycleOwner {
    LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
      @Override
      public Lifecycle getLifecycle() {  
          return mLifecycleRegistry;
      }
      
     void performCreate(){
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
      }
      
     void performStart(){
         mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
      }
      .....
     void performResume(){
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
      }  
    }
    

    Fragment中主要就是实现LifecycleOwner接口,然后通过LifecycleRegistry来分发各个生命周期的事件。LifecycleRegistry是整个Lifecycle组件最核心的功能。LifecycleRegistry的工作原理非常复杂,我们在之后的章节中再做介绍。

    Activity是如何实现Lifecycle的

    Activity在实现上并不类似Fragment,而是额外在Activity中加入了一个ReportFragment来实现对生命周期的分发,主要目的是为了兼容一些不继承自AppComponentActivity的Activity也可以使用Lifecycle的特性。核心源码如下:

    public class ComponentActivity extends Activity implements LifecycleOwner{
      private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
       @NonNull
       @Override
       public Lifecycle getLifecycle() {
          return mLifecycleRegistry;
       }
      
      protected void onCreate(Bundle bundle) {
          super.onCreate(savedInstanceState);
          ReportFragment.injectIfNeededIn(this); 
    }
    

    接下来我们继续分析ReportFragmentReportFragment中没有加载布局,所以他在Activity中实际是是一个不可见Fragment。它的源码也很简单,本质上就是通过FragmentManager将Fragment加载到Activity中,然后Fragment的生命周期发生变化时,获取Activity中的LifecycleRegistry对象,将事件分发出去。

    public class ReportFragment extends Fragment{
      public static void injectIfNeededIn(Activity activity) {
            android.app.FragmentManager manager = activity.getFragmentManager();
            if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
                manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
                manager.executePendingTransactions();
            }
      }
    
        @Override
        public void onStart() {
            super.onStart();
            dispatch(Lifecycle.Event.ON_START);
        }
    
        @Override
        public void onResume() {
            super.onResume();
            dispatch(Lifecycle.Event.ON_RESUME);
        }
    
        @Override
        public void onPause() {
            super.onPause();
            dispatch(Lifecycle.Event.ON_PAUSE);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            dispatch(Lifecycle.Event.ON_DESTROY);
        }
    
        private void dispatch(Lifecycle.Event event) {
             Lifecycle lifecycle = activity.getLifecycle();
             if (lifecycle instanceof LifecycleRegistry) {
                 ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
             }
    }  
    

    Lifecycle是如何分发宿主状态的

    观察者与宿主生命周期的对齐

    通过查看Fragment/Activity的源代码,我们发现LifecycleRegistry才是负责分发生命周期事件的核心,在分析LifecycleRegistry是如何进行事件分发之前,我们先来看看我们在Activity/Fragmnent中调用的addObserver()方法干了些什么。

     @Override
        public void addObserver(@NonNull LifecycleObserver observer) {
            ...
            // 初始化一个State状态值
            State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
            // 将宿主状态的初始值,和传递进来的`LifecycleObserver`封装成一个`ObserverWithState`对象
            ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
            ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
                    ...
                    // `calculateTargetState(observer)`计算得出当前宿主的状态
            State targetState = calculateTargetState(observer);
            mAddingObserverCounter++;
            // 循环比对宿主状态与观察者的状态,如果不同步,将`ObserverWithState`的状态前进到和宿主相同的状态
            while ((statefulObserver.mState.compareTo(targetState) < 0
                    && mObserverMap.contains(observer))) {
                pushParentState(statefulObserver.mState);
                // 根据观察者当前状态,得到它的下一步状态。需要注意,状态的前进是步进的,它并不会跳过事件,而是依次前进,多次分发。
                final Event event = Event.upFrom(statefulObserver.mState);
                ...
                // 分发状态
                statefulObserver.dispatchEvent(lifecycleOwner, event);
                popParentState();
                // mState / subling may have been changed recalculate
                targetState = calculateTargetState(observer);
            }
          ...
        }
    

    addObserver()的逻辑大致可以分为以下流程

    • 1.初始化一个State状态值
    • 2.将宿主状态的初始值,和传递进来的LifecycleObserver封装成一个ObserverWithState对象
    • 3.将ObserverWithState对象存入一个Map中
    • 4.calculateTargetState(observer)计算得出当前宿主的状态
    • 5.将ObserverWithState的状态前进到和宿主相同的状态
      • 5.1 分发状态变化,内部会调用onStateChanged()方法
                void dispatchEvent(LifecycleOwner owner, Event event) {
                State newState = event.getTargetState();
                mState = min(mState, newState);
                // 分发状态
                mLifecycleObserver.onStateChanged(owner, event);
                // 观察者,内部状态更新
                mState = newState;
            }
    

    通过上述分析,可以看出,addObserver方法主要就完成两个任务,1.将宿主和观察者关联起来;2.将观察者的生命周期与宿主对齐。
    但是我们有两点需要注意:

    • 第一:宿主的状态并不等同于宿主的生命周期,他们的关系如下图。


      宿主状态与生命周期.jpg
    • 第二:观察者在同步宿主状态时,是依次步进的。即使宿主状态与观察者的状态存在多个间距,也不会从INITIALIZED直接跳到STARTED
      反应在开发中,我们就会观察到,如果在Activity的OnStop中注册了一个观察者,那么注册完毕后,该观察者实际上会立即收到OnCreateOnStartOnResumeOnPause的回调,并最终收到OnStop的回调。

    宿主分发生命周期状态

    handleLifecycleEvent()是宿主在生命周期发生变化时,主动调用的方法,由他负责完成观察者的状态变化和事件分发,接下来我们就来看一下它的实现逻辑:

        public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
            ...
            moveToState(event.getTargetState());
        }
            ...Lifecycle
            // 根据Event推导出下一步的状态
            public State getTargetState() {
                switch (this) {
                    case ON_CREATE:
                    case ON_STOP:
                        return State.CREATED;
                    case ON_START:
                    case ON_PAUSE:
                        return State.STARTED;
                    case ON_RESUME:
                        return State.RESUMED;
                    case ON_DESTROY:
                        return State.DESTROYED;
                    case ON_ANY:
                        break;
                }
                throw new IllegalArgumentException(this + " has no target state");
            }
        ...    
        private void moveToState(State next) {
            ...
            // 更新宿主的状态
            mState = next;
            // 同步观察者的状态
            sync();
            ...
        }
    
        private void sync() {
            LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
            ...
           // isSynced():判断宿主的状态与观察者状态是否已经同步
            while (!isSynced()) {
                mNewEventOccurred = false;
                // 当宿主状态发生倒退时,同步观察者的状态,并分发相应的事件
                if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                    backwardPass(lifecycleOwner);
                }
                Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
                //当宿主状态发生前进时,同步观察者的状态,并分发相应的事件
                if (!mNewEventOccurred && newest != null
                        && mState.compareTo(newest.getValue().mState) > 0) {
                    forwardPass(lifecycleOwner);
                }
            }
            mNewEventOccurred = false;
        }
    

    相关逻辑在代码里已经有相应的注释,这里就不再赘述。到此为止我们就分析完了LifecycleRegistry是如何分发宿主生命周期事件了。

    相关文章

      网友评论

        本文标题:Android Jetpack 应用指南(四) - Lifecy

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