本文正在参与「金石计划 . 分割6万现金大奖」

前言

咱们都知道ActivityFragment都是有生命周期的,例如:onCreate()onStop()这些回调办法就代表着其生命周期状况。咱们开发者所做的一些操作都应该合理的操控在生命周期内,比方:当咱们在某个Activity中注册了播送接收器,那么在其onDestory()前要记住刊出掉,避免呈现内存走漏。

生命周期的存在,帮助咱们愈加方便地办理这些使命。但是,在日常开发中光凭 ActivityFragment 可不行,咱们通常还会运用一些组件来帮助咱们完成需求,而这些组件就不像ActivityFragment 相同能够很方便地感知到生命周期了。

假定当时有这么一个需求:

开发一个简易的视频播映器组件以供项目运用,要求在进入页面后注册播映器并加载资源,一旦播映器所在的页面不行见或许不坐落前台时就暂停播映,等到页面可见或许又恢复到前台时再继续播映,最终在页面毁掉时则刊出掉播映器。

试想一下:假如现在让你来完成该需求?你会怎样去完成呢?

完成这样的需求,咱们的播映器组件就需要获取到所在页面的生命周期状况,在onCreate()中进行注册,onResume()开端播映,onStop()暂停播映,onDestroy()刊出播映器。

最简单的办法:供给办法,露出给运用方,供其自己调用操控。

class VideoPlayerComponent(private val context: Context) {
    /**
     * 注册,加载资源
     */
    fun register() {
        loadResource(context)
    }
    /**
     * 刊出,开释资源
     */
    fun unRegister() {
        releaseResource()
    }
    /**
     * 开端播映当时视频资源
     */
    fun startPlay() {
        startPlayVideo()
    }
    /**
     * 暂停播映
     */
    fun stopPlay() {
        stopPlayVideo()
    }
}

然后,咱们的运用方MainActivity自己,自动在其相对应的生命周期状况进行操控调用相对应的办法。

class MainActivity : AppCompatActivity() {
    private lateinit var videoPlayerComponent: VideoPlayerComponent
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
	videoPlayerComponent = VideoPlayerComponent(this)
        videoPlayerComponent.register(this)
    }
    override fun onResume() {
        super.onResume()
        videoPlayerComponent.startPlay()
    }
    override fun onPause() {
        super.onPause()
        videoPlayerComponent.stopPlay()
    }
    override fun onDestroy() {
        videoPlayerComponent.unRegister()
        super.onDestroy()
    }
}

尽管完成了需求,但显然这不是最优雅的完成办法。一旦运用方忘掉在onDestroy()进行刊出播映器,就容易造成内存走漏,而忘掉刊出显然是一件很容易发生的工作。

回想初衷,之所以将办法露出给运用方来调用,便是因为咱们的组件本身无法感知到运用者的生命周期。所以,一旦咱们的组件本身能够感知到运用者的生命周期状况的话,咱们就不需要将这些办法露出出去了。

那么问题来了,组件怎么才干感知到生命周期呢?

答:Lifecycle !

直接上案例,借助 Lifecycle 咱们改进一下咱们的播映器组件

class VideoPlayerComponent(private val context: Context) : DefaultLifecycleObserver {
    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        register(context)
    }
    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        startPlay()
    }
    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        stopPlay()
    }
    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        unRegister()
    }
    /**
     * 注册,加载资源
     */
    private fun register(context: Context) {
        loadResource(context)
    }
    /**
     * 刊出,开释资源
     */
    private fun unRegister() {
        releaseResource()
    }
    /**
     * 开端播映当时视频资源
     */
    private fun startPlay() {
        startPlayVideo()
    }
    /**
     * 暂停播映
     */
    private fun stopPlay() {
        stopPlayVideo()
    }
}

改进完成后,咱们的调用方MainActivity只需要一行代码即可。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        lifecycle.addObserver(VideoPlayerComponent(this))
    }
}

这样是不是就优雅多了。

那这 Lifecycle 又是怎样感知到生命周期的呢?让咱们这就带着问题,动身探一探它的完成办法与源码!

假如让你来做,你会怎样做

在检查源码前,让咱们试着考虑一下,假如让你来完成Jetpack Lifecycle这样的功用,你会怎样做呢?该从何入手呢?

咱们的意图是不通过回调办法即可获取到生命周期,这其实便是解耦,完成解耦的一种很好办法便是利用调查者形式。

利用调查者形式,咱们就能够这么规划

我尝试以最简单的方式帮你梳理 Lifecycle

被调查者目标便是生命周期,而调查者目标则是需要知晓生命周期的目标,例如:咱们的三方组件。

接着咱们就详细探探源码,看一看Google是怎么完成的吧。

Google 完成办法

Lifecycle

一个代表着Android生命周期的笼统类,也便是咱们的笼统被调查者目标。

public abstract class Lifecycle {
    public abstract void addObserver(@NonNull LifecycleObserver observer);
    public abstract void removeObserver(@NonNull LifecycleObserver observer);
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY;
    }
    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
    }
}

内包括StateEvent分别者代表生命周期的状况与事情,一同定义了笼统办法addObserver(LifecycleObserver)removeObserver(LifecycleObserver)办法用于增加与删去生命周期调查者。

Event很好了解,就像是Activity | FragmentonCreate()onDestroy()等回调办法,它代表着生命周期的事情。

那这State又是什么呢?何为状况?他们之间又是什么联络呢?

Event 与 State 之间的联络

关于EventState之间的联络,Google官方给出了这么一张两者联络图

我尝试以最简单的方式帮你梳理 Lifecycle

乍一看,或许第一感觉不是那么直观,我整理了一下

我尝试以最简单的方式帮你梳理 Lifecycle

  • INITIALIZED:在ON_CREATE事情触发前。
  • CREATED:在ON_CREATE事情触发后以及ON_START事情触发前;或许在ON_STOP事情触发后以及ON_DESTROY事情触发前。
  • STARTED:在ON_START事情触发后以及ON_RESUME事情触发前;或许在ON_PAUSE事情触发后以及ON_STOP事情触发前。
  • RESUMED:在ON_RESUME事情触发后以及ON_PAUSE事情触发前。
  • DESTROYED:在ON_DESTROY事情触发之后。

Event代表生命周期发生变化那个瞬间点,而State则表示生命周期的一个阶段。这两者结合的好处便是让咱们能够愈加直观的感触生命周期,然后能够依据当时所在的生命周期状况来做出愈加合理操作行为。

例如,在LiveData的生命周期绑定调查者源码中,就会判别当时调查者目标的生命周期状况,假如当时是DESTROYED状况,则直接移除当时调查者目标。一同,依据调查者目标当时的生命周期状况是否>= STARTED来判别当时调查者目标是否是活泼的。

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
   ......
   @Override
   boolean shouldBeActive() {
      //依据调查者目标当时的生命周期状况是否 >= STARTED 来判别当时调查者目标是否是活泼的。
      return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
   }
  @Override
  public void onStateChanged(@NonNull LifecycleOwner source,
          @NonNull Lifecycle.Event event) {
      //依据当时调查者目标的生命周期状况,假如是DESTROYED,直接移除当时调查者
      Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
      if (currentState == DESTROYED) {
          removeObserver(mObserver);
          return;
      }
      ......
  }
  ......
}

其实EventState这两者之间的联络,在咱们生活中也是处处可见,例如:自动洗车。

我尝试以最简单的方式帮你梳理 Lifecycle

想必现在你对EventState之间的联络有了更好的了解了吧。

LifecycleObserver

生命周期调查者,也便是咱们的笼统调查者目标。

public interface LifecycleObserver {
}

所以,咱们想成为调查生命周期的调查者的话,就需要详细完成该接口,也便是成为详细调查者目标。

换句话说,便是假如你想成为调查者目标来调查生命周期的话,那就必须完成 LifecycleObserver 接口。

例如Google官方供给的 DefaultLifecycleObserverLifecycleEventObserver

我尝试以最简单的方式帮你梳理 Lifecycle

LifecycleOwner

正如其姓名相同,生命周期的持有者,所以像咱们的 Activity | Fragment 都是生命周期的持有者。

大白话很好了解,但代码应该怎么完成呢?

笼统概念 + 详细完成

笼统概念:定义 LifecycleOwner 接口。

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}

详细完成:Fragment 完成 LifecycleOwner 接口。

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner, HasDefaultViewModelProviderFactory, SavedStateRegistryOwner,
        ActivityResultCaller {
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
......
}

详细完成:Activity 完成 LifecycleOwner 接口。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        ContextAware,
        LifecycleOwner,
        ViewModelStoreOwner,
        HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner,
        ActivityResultRegistryOwner,
        ActivityResultCaller {
@NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
......
}

这样,Activity | Fragment 就都是生命周期持有者了。

疑问?在上方 Activity | Fragment 的类中,getLifecycle() 办法中都是回来mLifecycleRegistry,那这个 mLifecycleRegistry 又是什么玩意呢?

LifecycleRegistry

Lifecycle 的一个详细完成类。

LifecycleRegistry 负责办理生命周期调查者目标,并将最新的生命周期事情与状况及时通知给对应的生命周期调查者目标。

增加与删去调查者目标的详细完成办法。

//用户保存生命周期调查者目标
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>();
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    enforceMainThreadIfNeeded("addObserver");
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    //将生命周期调查者目标包装成带生命周期状况的调查者目标
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
    ... 省掉代码 ...
}
@Override
public void removeObserver(@NonNull LifecycleObserver observer) {
    mObserverMap.remove(observer);
}

能够从上述代码中发现,LifecycleRegistry 还对生命周期调查者目标进行了包装,使其带有生命周期状况。

static class ObserverWithState {
    //生命周期状况
    State mState;
    //生命周期调查者目标
    LifecycleEventObserver mLifecycleObserver;
    ObserverWithState(LifecycleObserver observer, State initialState) {
        //这里确保observer为LifecycleEventObserver类型
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        //并初始化了状况
        mState = initialState;
    }
    //分发事情
    void dispatchEvent(LifecycleOwner owner, Event event) {
        //依据 Event 得出当时最新的 State 状况
        State newState = event.getTargetState();
        mState = min(mState, newState);
        //触发调查者目标的 onStateChanged() 办法
        mLifecycleObserver.onStateChanged(owner, event);
        //更新状况
        mState = newState;
    }
}

将最新的生命周期事情通知给对应的调查者目标。

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    ... 省掉代码 ...
    ObserverWithState observer = mObserverMap.entrySet().getValue();
    observer.dispatchEvent(lifecycleOwner, event);
    ... 省掉代码 ...
    mLifecycleObserver.onStateChanged(owner, event);
}

handleLifecycleEvent()办法在什么时候被调用呢?

相信看到下方这个代码,你就理解了。

public class FragmentActivity extends ComponentActivity {
   ......
   final LifecycleRegistry mFragmentLifecycleRegistry = new LifecycleRegistry(this);
   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
   }
   @Override
   protected void onDestroy() {
       mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
   }
   @Override
   protected void onPause() {
       mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
   }
   @Override
   protected void onStop() {
       mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
   }
   ......
}

Activity | FragmentonCreate()onStart()onPause()等生命周期办法中,调用LifecycleRegistryhandleLifecycleEvent() 办法,然后将生命周期事情通知给调查者目标。

总结

Lifecycle通过调查者规划形式,将生命周期感知目标生命周期供给者充分解耦,不再需要通过回调办法来感知生命周期的状况,使代码变得愈加的精简。

尽管不通过Lifecycle,咱们的组件也是能够获取到生命周期的,但是Lifecycle的含义便是供给了统一的调用接口,让咱们的组件能够愈加方便的感知到生命周期,方便广达开发者。并且,Google以此推出了更多的生命周期感知型组件,例如:ViewModelLiveData。正是这些组件,让咱们的开发变得越来越简单。

相关文章推荐阅读:

  • 关于ViewModel的这几个问题,你都知道吗?
  • 为什么Google要将LiveData规划成粘性的
  • 为什么LiveData的调查者必须处于主线程

到此本篇文章就完毕啦,假如你有任何疑问或许不同的想法,欢迎在评论区留言与我一同探讨。

其实共享文章的最大意图正是等待着有人指出我的过错,假如你发现哪里有过错,请毫无保留的指出即可,谦虚讨教。

别的,假如你觉得文章不错,对你有所帮助,请帮我点个赞,就当鼓励,谢谢~