首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

Android生命周期感知组件codelab

2024-12-20 来源:化拓教育网

1、介绍

组件

Architecture components是一组Android库,可帮助您以稳健,可测试和可维护的方式构建应用程序。
此codelab向您介绍了用于构建Android应用程序的以下几个生命周期感知架构组件:

  • ViewModel - 提供一种创建和检索绑定到特定生命周期的对象的方法。 ViewModel通常存储视图数据的状态,并与其他组件通信,例如数据存储库或处理业务逻辑的域层。
  • LifecycleOwner / LifecycleRegistryOwner - LifecycleOwner和LifecycleRegistryOwner都是在AppCompatActivity和Support Fragment类中实现的接口。您可以将其他组件订阅到实现这些接口的所有者对象,以观察对所有者生命周期的更改。
  • LiveData - 允许您观察应用程序的多个组件之间的数据更改,而无需在它们之间创建明确,严格的依赖关系路径。 LiveData尊重应用程序组件的复杂生命周期,包括活动,片段,服务或应用程序中定义的任何LifecycleOwner。 LiveData通过暂停对已停止的LifecycleOwner对象的订阅以及取消对已完成的LifecycleOwner对象的订阅来管理观察者订阅。
你要建造什么

在此代码框中,您可以实现上述每个组件的示例。 首先是示例应用程序,然后通过一系列步骤添加代码,在进度时集成各种体系结构组件。

你需要什么
  • Android Studio 2.3或更高版本。
  • 熟悉Android活动生命周期。

2、第1步 - 设置您的环境

d928fd8587074072.png

旋转屏幕并注意计时器重置!
您现在需要更新应用程序以在屏幕旋转中保持状态。 您可以使用ViewModel,因为此类的实例在配置更改(例如屏幕旋转)后仍然存在。

3、第2步 - 添加ViewModel

在此步骤中,您将使用ViewModel在屏幕旋转中保持状态,并解决您在上一步中观察到的行为。 在上一步中,您运行了一个显示计时器的活动。 当配置更改(例如屏幕旋转)破坏活动时,将重置此计时器。

您可以使用ViewModel在活动或片段的整个生命周期中保留数据。 如上一步所示,活动是管理应用数据的不良选择。 活动和片段是短暂的对象,当用户与应用程序交互时,这些对象会频繁创建和销毁。 ViewModel也更适合管理与网络通信相关的任务,以及数据操作和持久性。

使用ViewModel保持计时器的状态

打开ChronoActivity2并检查类如何检索和使用ViewModel:

ChronometerViewModel chronometerViewModel
        = ViewModelProviders.of(this).get(ChronometerViewModel.class);

这指的是LifecycleOwner的一个实例。 只要LifecycleOwner的范围处于活动状态,该框架就会使ViewModel保持活动状态。 如果ViewModel的所有者因配置更改(例如屏幕旋转)而被销毁,则不会销毁ViewModel。 所有者的新实例重新连接到现有的ViewModel,如下图所示:


警告:活动或片段的范围从创建到完成(或终止),您不得与销毁混淆。 请记住,当旋转设备时,活动将被销毁,但与之关联的ViewModel的任何实例都不会被销毁。

试试看

运行应用程序(在“运行配置”下拉列表中选择“步骤2”),并在执行以下任一操作时确认计时器未重置:

  • 旋转屏幕。
  • 导航到另一个应用程序,然后返回。


但是,如果您或系统退出应用程序,则计时器将重置。

警告:系统会在生命周期所有者的整个生命周期中将ViewModel实例保留在内存中,例如片段或活动。 系统不会将ViewModel实例持久存储到长期存储中。

4、第3步 - 使用LiveData包装数据

在此步骤中,您将使用计时器的自定义计时器替换前面步骤中使用的计时器,并每秒更新UI。 Timer是一个java.util类,可用于在将来重复安排任务。 您将此逻辑添加到LiveDataTimerViewModel类,并使活动专注于管理用户和UI之间的交互。

当计时器通知时,活动会更新UI。 为了帮助避免内存泄漏,ViewModel不包含对活动的引用。 例如,配置更改(例如屏幕旋转)可能会导致ViewModel中的引用应该是应该进行垃圾回收的活动。 系统将保留ViewModel的实例,直到相应的活动或生命周期所有者不再存在。

警告:在ViewModel中存储对Context或View的引用可能导致内存泄漏。 避免使用引用Context或View类实例的字段。onCleared()方法对于取消订阅或清除对具有更长生命周期的其他对象的引用非常有用,但不能用于清除对Context或View对象的引用。

您可以将活动或片段配置为观察数据源,在更改时接收数据,而不是直接从ViewModel修改视图。 这种安排称为观察者模式。

注意:要将数据公开为可观察对象,请将类型包装在LiveData类中。

如果您使用了数据绑定库或其他反应库(如RxJava),您可能熟悉观察者模式。 LiveData是一个特殊的可观察类,它是生命周期感知的,只通知活跃的观察者。

LifecycleOwner

ChronoActivity3是LifecycleActivity的一个实例,它可以提供生命周期的状态。 这是类声明:

public class LifecycleActivity extends FragmentActivity implements LifecycleRegistryOwner {...}

LifecycleRegistryOwner用于将ViewModel和LiveData实例的生命周期绑定到活动或片段。 片段的等价类是LifecycleFragment。

更新ChronoActivity
  1. subscribe()方法中将以下代码添加到ChronoActivity3类以创建订阅:
mLiveDataTimerViewModel.getElapsedTime().observe(this, elapsedTimeObserver);
  1. 接下来,在LiveDataTimerViewModel类中设置新的已用时间值。 找到以下评论:
//TODO set the new value

用以下语句替换注释:

mElapsedTime.postValue(newValue);

运行该应用并在Android Studio中打开Android Monitor。 请注意,除非您导航到其他应用程序,否则日志每秒都会更新。 如果您的设备支持多窗口模式,您可能想尝试使用它。 旋转屏幕不会影响应用程序的行为方式。


注意:LiveData对象仅在活动或LifecycleOwner处于活动状态时发送更新。 如果您导航到其他应用程序,日志消息会暂停,直到您返回。 LiveData对象仅在其各自的生命周期所有者为STARTED或RESUMED时将订阅视为活动。

5、第4步 - 订阅生命周期事件

许多Android组件和库要求您:

  • 订阅或初始化组件或库。
  • 取消订阅或停止组件或库。

未能完成上述步骤可能会导致内存泄漏和细微错误。
生命周期所有者对象可以传递给生命周期感知组件的新实例,以确保他们了解生命周期的当前状态。
您可以使用以下语句查询生命周期的当前状态:

lifecycleOwner.getLifecycle().getCurrentState()

上面的语句返回一个状态,例如Lifecycle.State.RESUMEDLifecycle.State.DESTROYED
实现LifecycleObserver的生命周期感知对象还可以观察生命周期所有者状态的变化:

lifecycleOwner.getLifecycle().addObserver(this);

您可以注释对象以指示它在需要时调用适当的方法:

@OnLifecycleEvent(Lifecycle.EVENT.ON_RESUME)
void addLocationListener() { ... }
创建一个生命周期感知的组件

在此步骤中,您将创建一个对活动生命周期所有者作出反应的组件。 使用片段作为生命周期所有者时,类似的原则和步骤适用。
您可以使用Android框架的LocationManager获取当前的纬度和经度,并将其显示给用户。 此添加允许您:

  • 订阅更改并使用LiveData自动更新UI。
  • 根据活动状态的更改,创建注册和取消注册的LocationManager包装器。

您通常会将LocationManager订阅到活动的onStart()onResume()方法中的更改,并删除onStop()onPause()方法中的侦听器:

// Typical use, within an activity.

@Override
protected void onResume() {
    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mListener);
}

@Override
protected void onPause() {
    mLocationManager.removeUpdates(mListener);
}

在此步骤中,您将在名为BoundLocationManager的类中使用名为LifecycleRegistryOwner的LifecycleOwner实现。 BoundLocationManager类的名称指的是类的实例绑定到活动的生命周期。
要让类观察活动的生命周期,必须将其添加为观察者。 为此,请指示BoundLocationManager对象通过将以下代码添加到其构造函数来观察生命周期:

lifecycleOwner.getLifecycle().addObserver(this);

要在发生生命周期更改时调用方法,可以使用@OnLifecycleEvent批注。 使用BoundLocationListener类中的以下注释更新addLocationListener()removeLocationListener()方法:

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void addLocationListener() {
    ...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void removeLocationListener() {
    ...
}

注意:观察者被带到提供者的当前状态,因此不需要从构造函数中调用addLocationListener()。 当观察者被添加到生命周期所有者时,它会被调用。

旋转设备时,运行应用程序并验证日志监视器是否显示以下操作:

D/BoundLocationMgr: Listener added
D/BoundLocationMgr: Listener removed
D/BoundLocationMgr: Listener added
D/BoundLocationMgr: Listener removed

使用Android模拟器模拟更改设备的位置(单击三个点以显示扩展控件)。 TextView在更改时会更新:


6、第5步 - 在片段之间共享ViewModel

在片段之间共享ViewModel

使用ViewModel完成以下附加步骤,以启用片段与以下内容之间的通信:

  • 一项活动。
  • 片段的两个实例,每个实例都有一个SeekBar。
  • 具有LiveData字段的单个ViewModel。

运行此步骤并注意SeekBar的两个实例,它们彼此独立:


使用ViewModel连接片段,以便在更改一个SeekBar时更新另一个SeekBar:


注意:您应该将活动用作生命周期所有者,因为每个片段的生命周期是独立的。

显示全文