<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont

本文涉及的产品
转发路由器TR,750小时连接 100GB跨地域
简介: 综述对于Activity和Fragment的生命周期都不会陌生,同样在我们自己的项目中也会需要做一需要依赖Activity和Fragment生命周期的操作。

综述

对于Activity和Fragment的生命周期都不会陌生,同样在我们自己的项目中也会需要做一需要依赖Activity和Fragment生命周期的操作。例如在onSaveInstanceState执行后不可在对Fragment进行操作,又比如我们需要在Activity的onDestroy中做一些释放的操作避免内存泄漏的情况出现。通常我们大多数的业务逻辑都不会写在Activity或者我们的Fragment当中。这时候便需要写一系列的方法以便在Activity中调用。当业务逻辑复杂起来,所依赖的类逐渐变多,层次加深以后,这些操作尤其显得十分繁琐。很庆幸google给我们Android Architecture Components中Lifecycles可以解决这一问题。

Lifecycles使用

如何添加Lifecycles的依赖在这里就不再说明,直接在官网查看最新依赖即可。对于Lifecycles的使用非常的简单。在这里我们就以MVP模式为例,在P层中如果想在Activity或者Fragment的onCreate和onDestroy中对Presenter做一些初始化和释放的的操作,通常情况下会在P层写一个初始化和释放的方法并且在Activity中的onCreate和onDestroy中进行调用。现在通过Lifecycles来实现就简单的多了。下面通过代码来看一下Lifecycles的使用,在这里创建了一个MainActivity和其对应的Presenter。

创建一个MainActivity类

public class MainActivity extends AppCompatActivity implements LifecycleRegistryOwner {

    private final LifecycleRegistry mRegistry = new LifecycleRegistry(this);
    private MainPresenter presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        presenter = new MainPresenter();
        getLifecycle().addObserver(presenter);
    }

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

}

创建一个MainPresenter,在这里仅仅只是打印出部分生命周期的调用日志

public class MainPresenter implements LifecycleObserver{

    private static final String TAG = MainPresenter.class.getSimpleName();

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void onCreate(){
        Log.e(TAG,"onCreate");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume(){
        Log.e(TAG,"onResume");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause(){
        Log.e(TAG,"onPause");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy(){
        Log.e(TAG,"onDestroy");
    }
}

通过上面代码可以看出Lifecycles的使用是非常的简单。对首先在Activity或者Fragment中实现LifecycleRegistryOwner接口,当然也可以继承LifecycleActivity或者LifecycleFragment。在这里建议采用通过实现LifecycleRegistryOwner接口的方式。然后在创建的MainPresenter中实现LifecycleObserver接口,并且通过OnLifecycleEvent来指定相对应Activity生命周期的方法。最后在Activity中注册这个Presenter即可。下面来看一下运行结果。
这里写图片描述
注意:这里是用的Fragment实现LifecycleRegistryOwner接口时必须使用Support的Fragment而不是原生的Fragment,而对应的Activity也应该是FragmentActivity。 原因稍后说明。

Lifecycles源码分析

以下是基于1.0.0-alpha9版本的源码进行分析。对于Lifecycles这个lib来说,我们会有很多个类需要监听Activity或者Fragment的生命周期,当Activity或者Fragment的生命周期发生改变的时候会通知这些类来执行相对应的方法。从这里很容易看出,它实际上就是一个典型的观察着模式
Lifecycles是会在应用启动的时候通过一个ContentProvider完成初始化注册。可以看到在AndroidManifest.xml中注册了一个provider。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.arch.lifecycle.extensions"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="26" />

    <application>
        <provider
            android:name="android.arch.lifecycle.LifecycleRuntimeTrojanProvider"
            android:authorities="${applicationId}.lifecycle-trojan"
            android:exported="false"
            android:multiprocess="true" />
    </application>

</manifest>

可以在下面路径找到这个AndroidManifest。

/build/intermediates/exploded-aar/android.arch.lifecycle/extensions/1.0.0-alpha3/AndroidManifest.xml

找到LifecycleRuntimeTrojanProvider这个类,可以看到在这里对LifecycleDispatcher进行初始化操作,在应用启动的时候会对它进行初始化,其余的都是一些ContentProvider的默认配置。

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class LifecycleRuntimeTrojanProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        LifecycleDispatcher.init(getContext());
        ProcessLifecycleOwner.init(getContext());
        return true;
    }
    ......

从LifecycleDispatcher这个类的名字可以看出,他是对生命周期的事件进行分发处理的。
在这里看一下LifecycleDispatcher中初始化的方法。

static void init(Context context) {
    if (sInitialized.getAndSet(true)) {
        return;
    }
    ((Application) context.getApplicationContext())
            .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
}

在LifecycleDispatcher的初始化过程中,会在应用的Application中注册Activity生命周期的回调。DispatcherActivityCallback是LifecycleDispatcher中的一个内部类,下面在看一下这个类。

static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {
    private final FragmentCallback mFragmentCallback;

    DispatcherActivityCallback() {
        mFragmentCallback = new FragmentCallback();
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        if (activity instanceof FragmentActivity) {
            ((FragmentActivity) activity).getSupportFragmentManager()
                    .registerFragmentLifecycleCallbacks(mFragmentCallback, true);
        }
        ReportFragment.injectIfNeededIn(activity);
    }

    ......
}

在这个DispatcherActivityCallback中的核心代码是onActivityCreated方法,从这个方法里面做了两件事情,一是注册了Fragment的回调,二是创建了ReportFragment。其实这两件事情实际上就是对我们创建的Fragment和Activity的生命周期进行监听和事件分发。在这里分别来看一下是如何实现的。
1.监听Fragment的生命周期
在上面的第10~13行代码中,判断我们使用的Activity是FragmentActivity之后注册了Fragement生命周期的回调,同样FragmentCallback也是LifecycleDispatcher中的一个内部类。

@SuppressWarnings("WeakerAccess")
@VisibleForTesting
static class FragmentCallback extends FragmentManager.FragmentLifecycleCallbacks {

    @Override
    public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
        dispatchIfLifecycleOwner(f, ON_CREATE);

        if (!(f instanceof LifecycleRegistryOwner)) {
            return;
        }

        if (f.getChildFragmentManager().findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            f.getChildFragmentManager().beginTransaction().add(new DestructionReportFragment(),
                    REPORT_FRAGMENT_TAG).commit();
        }
    }
    ......
}

在FragmentCallback中我们可以清晰的看到,如果我们创建的Fragment实现了LifecycleRegistryOwner接口,在其相应的生命周期中对ON_CREATE,ON_START,ON_RESUME事件进行分发。这里在Fragment生命周期的回调中仅仅只是对Fragment一些启动事件的分发处理,那么对于Fragment销毁事件的处理则是通过DestructionReportFragment。也就是在获取到我们创建的FragmentActivity之后去add一个DestructionReportFragment对象,在DestructionReportFragment中完成ON_PAUSE,ON_STOP,ON_DESTROY事件的分发处理。DestructionReportFragment代码不在贴出。这样以来就完成了对Fragment生命周期事件的分发。
在这里会有两个疑问,第一,为什么要通过DestructionReportFragment来处理Fragment销毁事件的分发,而不是完全通过Fragment生命周期的回调来处理?第二,从注册Fragment的回调开始一直使用的都是Support中的Fragment,也就是说对于Fragment的生命周期事件的分发获取只支持Support中的Fragment,不支持原生的Fragment,为什么要这么做?
首先来看一下第一个问题,在Fragemnt的回调接口中,onFragmentStarted,onFragmentResumed等会在我们创建的Fragment的onStart和onResumed之后执行,对于销毁的生命周期,通过DestructionReportFragment来执行事件分发,会在我们创建的Fragment中的onPause等执行之前完成事件分发。这样就能在我们创建的Fragment初始化完成之后完成响应的启动事件处理,在销毁之前完成响应销毁事件的处理。
对于第二个问题在Android原生的Fragment中并没有提供对Fragment的生命周期有着相应的回调接口,如果使用add一个Fragment方式来处理,就会使得所有的事件都会提前到我们创建的Fragment生命周期执行之前进行处理。所以目前只支持Support中的Fragment。
2.监听Activity的生命周期
对于Activity生命周期的监听处理就很简单了,他是通过ReportFragment来同步的.

public class ReportFragment extends Fragment {

    private static final String REPORT_FRAGMENT_TAG = "android.arch.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";

    public static void injectIfNeededIn(Activity activity) {
        // ProcessLifecycleOwner should always correctly work and some activities may not extend
        // FragmentActivity from support lib, so we use framework fragments for activities
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            // Hopefully, we are the first to make a transaction.
            manager.executePendingTransactions();
        }
    }

    ......

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatchResume(mProcessListener);
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
        // just want to be sure that we won't leak reference to an activity
        mProcessListener = null;
    }

    ......
}

通过ReportFragment代码中可以看出是在Fragment相对应的生命周期中进行事件分发的。ReportFragment使用的是Android原生的Fragment,而不是Support中的Fragment,这样做的目的是为了兼容所有的Activity,使用Support中的Fragment的话只能适用于FragmentActivity了。使用ReportFragment的进行对相应的生命周期进行分发的好处就是不用直接依赖Activity生命周期的回调,讲这些事件交由Fragment处理,降低了对Activity的侵入性。
在对Fragment和Activity对应生命周期进行分发时,分别调用LifecycleDispatcher中的dispatchIfLifecycleOwner方法和ReportFragment中的dispatch方法。
LifecycleDispatcher中的dispatchIfLifecycleOwner方法:

private static void dispatchIfLifecycleOwner(Fragment fragment, Lifecycle.Event event) {
    if (fragment instanceof LifecycleRegistryOwner) {
        ((LifecycleRegistryOwner) fragment).getLifecycle().handleLifecycleEvent(event);
    }
}

ReportFragment中的dispatch方法:

private void dispatch(Lifecycle.Event event) {
    if (getActivity() instanceof LifecycleRegistryOwner) {
        ((LifecycleRegistryOwner) getActivity()).getLifecycle().handleLifecycleEvent(event);
    }
}

因为我们的Activity和Fragment实现了LifecycleRegistryOwner接口,所以在这里实际上调用的LifecycleRegistry的handleLifecycleEvent方法。

public void handleLifecycleEvent(Lifecycle.Event event) {
    mState = getStateAfter(event);
    if (mHandlingEvent || mAddingObserverCounter != 0) {
        mNewEventOccurred = true;
        // we will figure out what to do on upper level.
        return;
    }
    mHandlingEvent = true;
    sync();
    mHandlingEvent = false;
}

这个方法的核心部分是调用sync方法。

private void sync() {
    while (!isSynced()) {
        mNewEventOccurred = false;
        // no need to check eldest for nullability, because isSynced does it for us.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass();
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass();
        }
    }
    mNewEventOccurred = false;
}

在这里会根据将当前实际生命周期的状态和观察者所持有的状态进行比较,之后会根据观察者所持有事件的状态完成对事件的分发,并同步之前和之后的事件。这个方法只会被处于栈顶的Activity调用。以backwardPass方法为例。

private void backwardPass() {
    Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
            mObserverMap.descendingIterator();
    while (descendingIterator.hasNext() && !mNewEventOccurred) {
        Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
        ObserverWithState observer = entry.getValue();
        while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            Event event = downEvent(observer.mState);
            pushParentState(getStateAfter(event));
            observer.dispatchEvent(mLifecycleOwner, event);
            popParentState();
        }
    }
}

在这里可以看出是遍历mObserverMap来完成对所有观察者的分发,在每次注册一个observer的时候也就是调用LifecycleRegistry中addObserver的时候都会根据一个observer生成一个ObserverWithState对象,并保存在这个map对象中。对事件的处理也是调用ObserverWithState中的dispatchEvent方法。

static class ObserverWithState {
    State mState;
    GenericLifecycleObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.getCallback(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}

在这里可以看出通过Lifecycling的getCallback方法来获取一个GenericLifecycleObserver对象,通过调用GenericLifecycleObserver的onStateChanged方法来完成对生命周期的事件分发。在对Lifecycles使用过程中,是通过注解来完成对相应生命周期方法的调用。例如在上面的demo中rebuild代码之后会生成如下代码。

public class MainPresenter_LifecycleAdapter implements GenericLifecycleObserver {
  final MainPresenter mReceiver;

  MainPresenter_LifecycleAdapter(MainPresenter receiver) {
    this.mReceiver = receiver;
  }

  @Override
  public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) {
    if (event == Lifecycle.Event.ON_CREATE) {
      mReceiver.onCreate();
    }
    if (event == Lifecycle.Event.ON_RESUME) {
      mReceiver.onResume();
    }
    if (event == Lifecycle.Event.ON_PAUSE) {
      mReceiver.onPause();
    }
    if (event == Lifecycle.Event.ON_DESTROY) {
      mReceiver.onDestroy();
    }
  }

  public Object getReceiver() {
    return mReceiver;
  }
}

在这里生成的MainPresenter_LifecycleAdapter类中正是实现了GenericLifecycleObserver接口。而Lifecycling.getCallback正是通过反射来获取自动生成实现GenericLifecycleObserver接口的对象,执行其onStateChanged方法,实现了观察者与Activity生命周期的同步调用。

总结

对于Lifecycles这个lib,首先通过一个ContentProvider进行初始化,监听处于栈顶的Activity的onCreateActivity方法,并通过ReportFragment获取Activity的生命周期,通过FragmentCallback和DestructionReportFragment来获取Fragment生命周期。之后将其生命周期事件分发到已经注册过的Observer并交由ObserverWithState来处理。

附录

官方Demo: https://github.com/googlesamples/android-architecture-components
官方文档:https://developer.android.com/topic/libraries/architecture/lifecycle.html

相关文章
|
Web App开发 新零售 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
1.尽可能地了解需求,系统层面适用开闭原则 2.模块化,低耦合,能快速响应变化,也可以避免一个子系统的问题波及整个大系统 3.
748 0
|
Web App开发 前端开发 Android开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
使用MAT分析内存泄露 对于大型服务端应用程序来说,有些内存泄露问题很难在测试阶段发现,此时就需要分析JVM Heap Dump文件来找出问题。
779 0
|
Web App开发 前端开发 Java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
服务端需在vm arguments一栏下加上    -agentlib:jdwp=transport=dt_socket,server=y,address=8000 并以run模式启动 如果以debug模式启动服务端...
721 0
|
Web App开发 前端开发 程序员
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
Facebook 内部分享:不论你如何富有,你都赚不到更多的时间,你也回不到过去。没有那么多的假如,只有指针滴答的时光飞逝和你应该好好把握的现在,以下25张PPT的分享将为您带来时间价值管理的技巧。
613 0
|
Web App开发 前端开发 Linux
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
[root@hadoop058 ~]# mii-tool eth0: negotiated 100baseTx-FD, link ok 100M linux 下查看网卡工作速率 Ethtool是用于查询及设置网卡参数的命令。
646 0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
生产服务器环境最小化安装后 Centos 6.5优化配置备忘 本文 centos 6.5 优化 的项有18处,列表如下: 1、centos6.
1544 0
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
一个典型的星型模式包括一个大型的事实表和一组逻辑上围绕这个事实表的维度表。  事实表是星型模型的核心,事实表由主键和度量数据两部分组成。
537 0

热门文章

最新文章