墨星写作网站,网站建设使用的什么语言,建筑直聘网,搜索李晓峰文章目录 背景示例LifeCycle的原理LifecycleOwner自定义LifecycleOwnerLifecycleObserver 示例改进使用LifecycleService解耦Service与组件整个应用进程的生命周期ProcessLifecycleOwner 背景
在Android应用程序开发中#xff0c;解耦很大程度上表现为系统组件的生命周期与普… 文章目录 背景示例LifeCycle的原理LifecycleOwner自定义LifecycleOwnerLifecycleObserver 示例改进使用LifecycleService解耦Service与组件整个应用进程的生命周期ProcessLifecycleOwner 背景
在Android应用程序开发中解耦很大程度上表现为系统组件的生命周期与普通组件之间的解耦。普通组件在使用过程中通常需要依赖于系统组件的生命周期。有时候我们不得不在系统组件的生命周期回调方法中主动对普通组件进行调用或控制。因为普通组件无法主动获知系统组件的生命周期事件。
我们希望我们对自定义组件的管理不依赖于页面生命周期的回调方法。同时在页面生命周期发生变化时也能够及时收到通知。这在组件化和架构设计中显得尤为重要。 为此Google提供了LifeCycle作为解决方案。LifeCycle可以帮助开发者创建可感知生命周期的组件。这样组件便能够在其内部管理自己的生命周期从而降低模块间的耦合度并降低内存泄漏发生的可能性。LifeCycle不只对Activity/Fragment有用在Service和Application中也能大显身手。 示例
Android开发中经常需要管理生命周期。举个栗子我们需要获取用户的地址位置当这个Activity在显示的时候我们开启定位功能然后实时获取到定位信息当页面被销毁的时候需要关闭定位功能。
internal class MyLocationListener(private val context: Context,private val callback: (Location) - Unit
) {fun start() {// 连接系统定位服务以及其他业务}fun stop() {//断开系统定位服务}
}class MyActivity : AppCompatActivity() {private lateinit var myLocationListener: MyLocationListeneroverride fun onCreate(...) {myLocationListener MyLocationListener(this) { location -...}}public override fun onStart() {super.onStart()myLocationListener.start()}public override fun onStop() {super.onStop()myLocationListener.stop()}
}
虽然此示例看起来没问题但在真实的应用中最终会有太多管理界面和其他组件的调用以响应生命周期的当前状态。管理多个组件会在生命周期方法如 onStart() 和 onStop()中放置大量的代码这使得它们难以维护。
此外无法保证组件会在 Activity 或 Fragment 停止之前启动。在我们需要执行长时间运行的操作如 onStart() 中的某种配置检查时尤其如此。这可能会导致出现一种竞态条件在这种条件下onStop() 方法会在 onStart() 之前结束这使得组件留存的时间比所需的时间要长。
class MyActivity : AppCompatActivity() {private lateinit var myLocationListener: MyLocationListeneroverride fun onCreate(...) {myLocationListener MyLocationListener(this) { location -// update UI}}public override fun onStart() {super.onStart()Util.checkUserStatus { result -// what if this callback is invoked AFTER activity is stopped?if (result) {myLocationListener.start()}}}public override fun onStop() {super.onStop()myLocationListener.stop()}} Lifecycle类是一个持有组件(activity或fragment)生命周期信息的类其他对象可以观察该状态。Lifecycle使用两个重要的枚举部分来管理对应组件的生命周期的状态: Event:生命周期事件由系统来分发这些事件对应于Activity和Fragment的生命周期函数。 State:Lifecycle对象所追踪的组件的当前状态 LifeCycle的原理
Jetpack为我们提供了两个类:
LifecycleOwner: 被观察者LifecycleObserver: 观察者
即通过观察者模式实现对页面生命周期的监听。
public class AppCompatActivity extends FragmentActivity implements AppCompatCallback,TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider {
}
public class FragmentActivity extends ComponentActivity implementsActivityCompat.OnRequestPermissionsResultCallback,ActivityCompat.RequestPermissionsRequestCodeValidator {
} public class ComponentActivity extends androidx.core.app.ComponentActivity implementsLifecycleOwner,ViewModelStoreOwner,SavedStateRegistryOwner,OnBackPressedDispatcherOwner {private final LifecycleRegistry mLifecycleRegistry new LifecycleRegistry(this);public Lifecycle getLifecycle() {return mLifecycleRegistry;}
}
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,ViewModelStoreOwner, SavedStateRegistryOwner {
} ComponentActivity和Fragment已经默认实现了LifecycleOwner接口。代表有生命周期
LifecycleOwner
那什么是LifecycleOwner呢实现LifecycleOwner接口就表示这是个有生命周期的类他有一个getLifecycle()方法是必须实现的。 //一个具有Android生命周期的类。自定义组件可以使用这些事件来处理生命周期更改而无需在Activity或Fragment中实现任何代码。
SuppressWarnings({WeakerAccess, unused})
public interface LifecycleOwner {/*** Returns the Lifecycle of the provider.*/NonNullLifecycle getLifecycle();
}从以上源码可知Activity和Fragment已经替我们实现了被观察者应该实现的那一部分代码。因此我们不需要再去实现这部分代码。当我们希望监听Activity的生命周期时只需要实现观察者那一部分的代码即让自定义组件实现LifecycleObserver接口即可。该接口没有接口方法无须任何具体实现。
对于前面提到的监听位置的例子。可以把MyLocationListener实现LifecycleObserver,然后在LifecycleActivityFragment的onCreate方法中初始化。这样MyLocationListener就能自行处理生命周期带来的问题。
自定义LifecycleOwner
如果想在自定义的类中实现LifecyclerOwner就需要用到LifecycleRegistry类,并且需要自行发送Event:
class MyActivity : Activity(), LifecycleOwner {private lateinit var lifecycleRegistry: LifecycleRegistryoverride 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
/*** Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on* {link OnLifecycleEvent} annotated methods.* see Lifecycle Lifecycle - for samples and usage patterns.//-------------* 将类标记为LifecycleObserver。它没有任何方法而是依赖于*link OnLifecycleEvent注释的方法。*请参阅生命周期-了解示例和使用模式。*/
SuppressWarnings(WeakerAccess)
public interface LifecycleObserver {}注释上写的很明白该接口依赖OnLifecycleEvent的注解方法
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.METHOD)
public interface OnLifecycleEvent {Lifecycle.Event value();
}
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
}示例改进
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// lifecycle是LifecycleOwner接口的getLifecycle()方法得到的lifecycle.addObserver(MyObserver()) }
}在Activity中只需要引用MyObserver即可不用再关心Activity生命周期变化对该组件所带来的影响。生命周期的管理完全交给MyObserver内部自行处理。在Activity中要做的只是通过getLifecycle().addObserver()方法将观察者与被观察者绑定起来。
class MyObserver : LifecycleObserver {OnLifecycleEvent(Lifecycle.Event.ON_RESUME)fun connectListener() {...//填写逻辑业务代码}OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)fun disconnectListener() {...//填写逻辑业务代码}
}上面的lifecycle.addObserver(MyObserver()) 的完整写法应该是aLifecycleOwner.getLifecycle().addObserver(new MyObserver())而aLifecycleOwner一般是实现了LifecycleOwner的类比如Activity/Fragment
internal class MyLocationListener(private val context: Context,private val lifecycle: Lifecycle,private val callback: (Location) - Unit): LifecycleObserver {private var enabled falseOnLifecycleEvent(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}
}对于组件中那些需要在页面生命周期发生变化时得到通知的方法我们需要在这些方法上使用OnLifecycleEventLifecycle.Event.ON_XXX标签进行标识。这样当页面生命周期发生变化时这些被标识过的方法便会被自动调用。
LifeCycle完美解决了组件对页面生命周期的依赖问题使组件能够自己管理其生命周期而无须在页面中对其进行管理。这无疑大大降低了代码的耦合度提高了组件的复用程度也杜绝了由于对页面生命周期管理的疏忽而引发的内存泄漏问题这在项目工程量大的情况下是非常有帮助的。
使用LifecycleService解耦Service与组件 拥有生命周期概念的组件除了Activity和Fragment还有一个非常重要的组件是Service。为了便于对Service生命周期的监听达到解耦Service与组件的目的Android提供了一个名为LifecycleService的类。该类继承自Service并实现了LifecycleOwner接口。与Activity/Fragment类似它也提供了一个名为getLifecycle()的方法供我们使用。 想要使用LifecycleService必须先增加lifecycle-service的依赖:
implementation androidx.lifecycle:lifecycle-service:2.3.1结构
public class LifecycleServiceextends Service implements LifecycleOwner
java.lang.Object↳ android.content.Context↳ android.content.ContextWrapper↳ android.app.Service↳ androidx.lifecycle.LifecycleService 源码
public class LifecycleService extends Service implements LifecycleOwner {private final ServiceLifecycleDispatcher mDispatcher new ServiceLifecycleDispatcher(this);CallSuperOverridepublic void onCreate() {mDispatcher.onServicePreSuperOnCreate();super.onCreate();}CallSuperNullableOverridepublic IBinder onBind(NonNull Intent intent) {mDispatcher.onServicePreSuperOnBind();return null;}SuppressWarnings(deprecation)CallSuperOverridepublic 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().CallSuperOverridepublic int onStartCommand(Nullable Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}CallSuperOverridepublic void onDestroy() {mDispatcher.onServicePreSuperOnDestroy();super.onDestroy();}OverrideNonNullpublic Lifecycle getLifecycle() {return mDispatcher.getLifecycle();}
}整个应用进程的生命周期ProcessLifecycleOwner
具有生命周期的系统组件除Activity、Fragment、Service外还有Application。很多时候我们会遇到这样的需求我们想知道应用程序当前处在前台还是后台或者当应用程序从后台回到前台时我们能够得到通知。有不少方案能够实现该需求但都不够好。在此之前Google并没有为该需求提供官方解决方案直到LifeCycle的出现。
需要先添lifecycle-process的依赖:
implementation androidx.lifecycle:lifecycle-process:2.3.1源码
/*** Class that provides lifecycle for the whole application process.* p* You can consider this LifecycleOwner as the composite of all of your Activities, except that* {link Lifecycle.Event#ON_CREATE} will be dispatched once and {link Lifecycle.Event#ON_DESTROY}* will never be dispatched. Other lifecycle events will be dispatched with following rules:* ProcessLifecycleOwner will dispatch {link Lifecycle.Event#ON_START},* {link Lifecycle.Event#ON_RESUME} events, as a first activity moves through these events.* {link Lifecycle.Event#ON_PAUSE}, {link Lifecycle.Event#ON_STOP}, events will be dispatched with* a bdelay/b after a last activity* passed through them. This delay is long enough to guarantee that ProcessLifecycleOwner* wont send any events if activities are destroyed and recreated due to a* configuration change.** p* It is useful for use cases where you would like to react on your app coming to the foreground or* going to the background and you dont need a milliseconds accuracy in receiving lifecycle* events.*/
/**
翻译
*为整个应用程序流程提供生命周期的类。
*您可以将此LifecycleOwner视为所有活动的组合除了
*link Lifecycle。事件#ON_CREATE将被调度一次并且linkLifecycle。事件#ON_DESTROY
*永远不会被派遣。其他生命周期事件将按照以下规则进行调度
*ProcessLifecycleOwner将调度link Lifecycle。事件#ON_START
*linkLifecycle.Event#ON_RESUME事件作为第一个活动在这些事件中移动。
*link Lifecycle。Event#ON_PAUSElink Lifecycle。Event#ON_STOP事件将与上次活动后的a延迟穿过他们。此延迟足够长可以保证ProcessLifecycleOwner
*如果活动由于配置更改。
*它适用于您希望对应用程序进入前台或
*进入后台在接收生命周期中不需要毫秒的准确性事件。
*/
SuppressWarnings(WeakerAccess)
public class ProcessLifecycleOwner implements LifecycleOwner {ProcessLifecycleOwner的使用方式与Activity、Fragment和Service是类似的其本质也是观察者模式。由于我们要观察的是整个应用程序因此需要在Application中进行相关代码的编写。
class StApplication : Application() {companion object {private lateinit var instance: Applicationfun getInstance() instance}override fun onCreate() {super.onCreate()instance thisProcessLifecycleOwner.get().lifecycle.addObserver(MyApplicationObserver())}
}
class MyApplicationObserver : LifecycleObserver {OnLifecycleEvent(Lifecycle.Event.ON_CREATE)fun onCreate() {}// 前台出现时调用OnLifecycleEvent(Lifecycle.Event.ON_START)fun onStart() {Log.e(xoliu, onStart)}// 前台出现时调用OnLifecycleEvent(Lifecycle.Event.ON_RESUME)fun onResume() {Log.e(xoliu, onResume)}// 退出到后台时调用OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)fun onPause() {Log.e(xoliu, onPause)}// 退出到后台时调用OnLifecycleEvent(Lifecycle.Event.ON_STOP)fun onStop() {Log.e(xoliu, onStop)}
}当应用程序从后台回到前台或者应用程序被首次打开时会依次调用Lifecycle.Event.ON_START和Lifecycle.Event.ON_RESUME。 当应用程序从前台退到后台用户按下Home键或任务菜单键会依次调用Lifecycle.Event.ON_PAUSE和Lifecycle.Event.ON_STOP。需要注意的是这两个方法的调用会有一定的延后。这是因为系统需要为“屏幕旋转由于配置发生变化而导致Activity重新创建”的情况预留一些时间。也就是说系统需要保证当设备出现这种情况时这两个事件不会被调用。因为当旋转屏幕时你的应用程序并没有退到后台它只是进入了横/竖屏模式而已。