Lifecycle——Google组件开发

2017年Google I/O大会不仅发布了O预览版,同时还将kotlin作为安卓开发的新宠儿。今天要介绍的是Google推出的应用架构组件。
  众所周知,安卓开发架构一直很自由,从MVC到MVP、MVVM等,今年I/O大会上Google也推出了一份关于应用架构的最佳实践指南。
  Android框架具有明确的API来处理与操作系统的联系点,例如Activity,但这些是进入应用程序的入口点,而不是为应用程序架构构建块,框架组件不会强制您将数据模型与UI组件分开,或提供一种清晰的方式来保持与生命周期无关的数据。

Google官方架构

  • 不要在应用程序组件中保存任何应用数据或状态,并且组件间也不应该相互依赖
  • 通过 model 驱动应用 UI,并尽可能的持久化

官方架构构建演示

Android Framework中定义的大多数应用程序组件都附有生命周期,这些生命周期由运行的操作系统或框架代码进行管理。它们是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;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // update UI
        });
  }

    public void onStart() {
        super.onStart();
        myLocationListener.start();
    }

    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}

上面的代码看起来就像我们平常的代码风格,但在一个真实的应用程序中,可能会遇到大量相似的调用,从而使onStart()和onStop()方法变得非常臃肿。另外如果一些组件不能在onStart()中启动,我们需要在启动位置观察器之前检查一些配置怎么办?在某些情况下,可以在Activity停止后检查完成,这意味着myLocationListener.start()将被调用myLocationListener.stop()之后,基本上保持连接。

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, location -> {
            // update UI
        });
    }

    public void onStart() {
        super.onStart();
        Util.checkUserStatus(result -> {
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                myLocationListener.start();
            }
        });
    }

    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}

Lifecycles 提供了一系列方法,可帮助您以弹性和孤立的方式解决这些问题。

Lifecycles

LIfecycle是一个保存有关组件生命周期状态的信息,并允许其他对象观察此状态的类,将系统组件(Activity、Fragment 等等)的生命周期分离到 Lifecycle 类,Lifecycle 类允许其他类作为观察者,在外部观察系统组件生命周期的变化。它使用两个主要枚举来跟踪其关联组件的生命周期状态。

  • Event:这些是从框架和Lifecycle类调度的生命周期事件。这些事件映射到Activity和Fragment中的回调事件。
  • State:由Lifecycle对象跟踪的组件的当前状态

首先通过向其方法添加注解@OnLifecycleEvent来监视组件的生命周期状态

public class MyObserver implements LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    public void onAny(LifecycleOwner owner, Lifecycle.Event event) {
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
    }
}
aLifecycleOwner.getLifecycle().addObserver(new MyObserver());

然后在 LifecycleRegistryOwner 比如 LifecycleActivity 加入上面最后一行代码

在Activity和Fragment中实现LifecycleOwner。通过实现内置的LifecycleRegistryOwner接口(而不是扩展LifecycleFragment或LifecycleActivity),任何Activity和Fragment都可以转换为LifecycleOwner

public class MyFragment extends Fragment implements LifecycleRegistryOwner {
    LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}

如果您有一个要创建LifecycleOwner的自定义类,则可以使用LifecycleRegistry类,但是您需要将事件转发到该类中。如果片段和活动实现了LifecycleRegistryOwner接口,则此转发将自动完成。

如果观察者指定LifeCycle处于Started或者RESUMED状态,LiveData会将观察者视为活动状态,并通知其数据的变化。
有关LiveData会在后面介绍。

LifecycleOwner

LifeCycleOwner是一个只有一个方法的接口用于表明其有一个LifeCycle对象。这个方法为getLifecycle(),它必须由类实现。
  LifecycleOwner从各个类(如Activity和Fragment)抽象生命周期的所有权,并允许编写可与两者兼容的组件。Activity和Fragment只要实现这个接口就能配合LifeCycle实现生命周期监听。任何自定义应用程序类都可以实现LifecycleOwner接口。

注意 : 由于Lifecycles项目处于alpha阶段,因此Fragment和AppCompatActivity类无法实现(因为我们无法将稳定组件的依赖关系添加到不稳定的API)。在Lifecycles稳定之前,为了方便起见,提供了LifecycleActivity和LifecycleFragment类。Lifecycles项目发布后,支持库片段和活动将实现LifecycleOwner接口;当时将不推荐使用LifecycleActivity和LifecycleFragment。

对于上面的示例,我们可以使MyLocationListener类成为LifecycleObserver,并使用onCreate上的生命周期进行初始化,并在此之后不再担心。这允许MyLocationListener类自足,这意味着它可以在必要时进行自己的清理。

class MyActivity extends LifecycleActivity {
    private MyLocationListener myLocationListener;

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

为了简化此用例,Lifecycle类允许其他对象查询当前状态

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.getState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void stop() {
        // disconnect if connected
    }
}

通过这个实现,我们的LocationListener类是完全生命周期感知的;它可以进行自己的初始化和清理而不受Activity或者Fragment的管理。如果我们需要从另一个Activity或另一个Fragment使用我们的LocationListener,我们需要做的就是初始化它。所有的安装和拆卸操作都将由类本身管理。

可以与Lifecycle一起使用的类称为生命周期感知组件。鼓励提供需要使用Android生命周期的类的库可以提供生命周期感知组件,以便客户端可以轻松地在客户端集成这些类,而无需手动生命周期管理。

LiveData是生命周期感知组件的示例。与ViewModel一起使用LiveData可以在遵循Android生命周期的情况下,更容易地使用数据填充UI

Lifecycle实践准则

  • 保持UI控制器(Activity和Fragment)尽可能体积小。他们不应该试图获取他们的数据;而是使用ViewModel来执行此操作,并观察LiveData以将更改反映到视图中
  • 尝试编写数据驱动的UI,您的UI控制器的责任是在数据更改时更新视图,或将用户操作通知给ViewModel
  • 将您的数据逻辑放在ViewModel类中。 ViewModel应该作为UI控制器和其他应用程序之间的连接器。请注意,ViewModel不是提取数据(例如,从网络)的责任。相反,ViewModel应该调用相应的组件来执行此工作,然后将结果提供给UI Controller。
  • 使用数据绑定在您的视图和UI控制器之间具有干净的界面。这将允许您使您的视图更具声明性,并最大限度地减少您需要在活动和片段中写入的更新代码。如果您更喜欢在Java中执行此操作,请使用像Butter Knife这样的库来避免使用样板代码并进行更好的抽象。
  • 如果您有一个复杂的UI,请考虑创建一个Presenter类来处理UI修改。这通常是过度的,但可能有助于使您的UI更容易测试。
  • 不要在ViewModel中引用View或Activity上下文。如果ViewModel超过活动(在配置更改的情况下),您的活动将被泄露,并且不正确地垃圾回收

你可能感兴趣的:(Lifecycle——Google组件开发)