Android开发经验谈Android架构程序员

Architecture Components 知识梳理(1)

2018-07-02  本文已影响154人  泽毛

一、概述

听说这一套ToolKit已经有很长一段时间了,一直没有系统的学习过,前几天有同事在项目中通过Lifecycles解决了监听Activity生命周期的问题,不得不说,真的是一套强大的框架,除此之外,前段时间Google还更新了NavigationPagingWorkManager用来解决 页面的管理 以及 任务的调度 问题,更激发了我学习的动力。

依照惯例,先从最基本的Demo学起,然后再去分析源码。

二、导入依赖

根目录build.gradle文件中,加上google()的远程仓库声明(现在AS创建的工程已经默认包含了该声明)。

allprojects {
    repositories {
        jcenter()
        //加上这一句。
        google()
    }
}

当我们使用了'com.android.support:appcompat-v7:27.1.1'时,其实已经默认导入了lifecycles相关的库,由此可见,这确实是之后的一个趋势。

默认导入的依赖

如果我们没有使用support:appcompat,那么就需要自己去声明依赖,当然并不是说要导入全部的依赖,而是可以根据需要去选择对应的依赖库,具体的说明在注释中。

dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // alternatively - just ViewModel
    implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" // use -ktx for Kotlin
    // alternatively - just LiveData
    implementation "android.arch.lifecycle:livedata:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData), Support library depends on this lightweight import
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"

    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
    // alternately - if using Java8, use the following instead of compiler
    implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

    // optional - ReactiveStreams support for LiveData
    implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"

    // optional - Test helpers for LiveData
    testImplementation "android.arch.core:core-testing:$lifecycle_version"
}

这里,我们直接使用appcompat当中导入的组件即可。

三、Lifecycle

3.1 解决的问题

Android开发当中,生命周期 是一个很重要的东西,因为我们往往需要在页面创建onCreate、页面展示onResume,和页面销毁onDestroy的时候,去进行业务逻辑的处理,而在此之前,我们只能通过ActivityFragment才能收到生命周期的回调,而其它的组件,例如Fragment当中的View需要收到生命周期的回调,那么只能通过ActivityFragment去通知它,这就造成了很多冗余的代码,特别是当我们期望提供一个View作为SDK给接入方时,又无形中增加了接入方的成本。

如果任何一个对象,通过观察者的方式,能够收到Activity/Fragment生命周期的各种回调就好了。没错!Lifecycle就是这么一个东西!

3.2 示例

    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }

在这些方法中添加Log用于调试:

public class LiveObserver implements LifecycleObserver {

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

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

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStart() {
        Log.d(TAG, "onStart()");
    }

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

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

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onStop() {
        Log.d(TAG, "onStop()");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy() {
        Log.d(TAG, "onDestroy()");
    }
}
public class LiveAppCompactActivity extends AppCompatActivity {

    private Button mBtnBind;
    private Button mBtnUnBind;
    private LifecycleObserver mObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_appcompact);
        mBtnBind = findViewById(R.id.bt_bind);
        mBtnBind.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mObserver == null) {
                    mObserver = new LiveObserver();
                    getLifecycle().addObserver(mObserver);
                }
            }
        });
        mBtnUnBind = findViewById(R.id.bt_unbind);
        mBtnUnBind.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mObserver != null) {
                    getLifecycle().removeObserver(mObserver);
                    mObserver = null;
                }
            }
        });

    }
}

3.3 模拟场景

场景一:点击绑定按钮

当界面完全可见的时候,我们点击“绑定”按钮,Log输出为:

点击绑定按钮后输出

场景二:点击绑定按钮,点击解绑按钮

没有任何输出。

场景三:再次点击绑定按钮

再次点击绑定按钮

场景四:在绑定状态下,锁屏或者按 Home 回到桌面

锁屏或按 Home 回到说面

场景五:解锁或者点击图标重新进入

解锁或者点击图标重新进入

场景六:按 Back 回到桌面

按 Back 回到桌面

场景结论

3.4 不使用 AppCompactActivity 实现

假如我们使用的不是AppCompactActivity,那么要怎么达到和3.2中一样的效果呢,实现方式如下:

整体的实现代码如下所示:

/**
 * 1.需要让 Activity 实现 LifecycleOwner 接口。
 */
public class LiveActivity extends Activity implements LifecycleOwner {

    private Button mBtnBind;
    private Button mBtnUnBind;
    //2.创建 mLifecycleRegistry 对象,其构造函数为实现了 LifecycleOwner 的对象。
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    private LifecycleObserver mObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live);
        mBtnBind = findViewById(R.id.bt_bind);
        mBtnBind.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mObserver == null) {
                    mObserver = new LiveObserver();
                    //4.1 注册的方法和之前相同。
                    getLifecycle().addObserver(mObserver);
                }
            }
        });
        mBtnUnBind = findViewById(R.id.bt_unbind);
        mBtnUnBind.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mObserver != null) {
                    //4.2 反注册的方法和之前相同。
                    getLifecycle().removeObserver(mObserver);
                    mObserver = null;
                }
            }
        });
    }

    /**
     * 3.该函数返回 mLifecycleRegistry。
     *
     * @return 返回 mLifecycleRegistry。
     */
    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

其效果和之前3.3中的表现是一致的。

四、实现原理

有没有感到很神奇,我们是怎么让一个独立的对象和Activity/Fragment的生命周期关联起来的呢。通过源码我们可以发现,有以下两个类实现了LifecycleOwner接口:

@RestrictTo(LIBRARY_GROUP)
public class SupportActivity extends Activity implements LifecycleOwner {

    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
   
}
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner {

    LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
   
}

当我们分析完之后,会发现这两种使用的是不同的方式来实现我们最终看到的效果的。

4.1 使用 Activity 的 getLifecycle 注册

当我们使用SupportActivitygetLifecycle(),其实系统在Activity启动的时候 偷偷 地为我们添加了一个没有界面的ReportFragment

@RestrictTo(LIBRARY_GROUP)
public class SupportActivity extends Activity implements LifecycleOwner {
    
    @Override
    @SuppressWarnings("RestrictedApi")
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在 onCreate 方法当中偷偷地添加。
        ReportFragment.injectIfNeededIn(this);
    }

}

用过Fragment的同学们都知道,Fragment的生命周期是和它所在的Activity绑定的,那么当Activity的状态变化时,Fragment的生命周期就会被回调,我们来看一下ReportFragment是怎么处理的:

public class ReportFragment extends Fragment {

    @Override
    public void onResume() {
        super.onResume();
        //这里会去分发事件。
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        //这里的 activity 就是我们上面的 SupportActivity,而 getLifecycle 就返回了 LifecycleRegistry 对象。
        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }
}

接着,就会走到LifecycleRegistryhandleLifecycleEvent方法当中,具体的逻辑如下所示,最终会通知到它内部所持有的LifecycleObserver

public class LifecycleRegistry extends Lifecycle {
    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
       //获取下一步的状态。
       State next = getStateAfter(event);
        //转移到该状态。
        moveToState(next);
    }

    private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
        //状态同步。
        sync();
        mHandlingEvent = false;
    }

    private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "
                    + "new events from it.");
            return;
        }
        while (!isSynced()) {
            mNewEventOccurred = false;
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                //1.向后转移。
                backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                //2.向前转移
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

    private void forwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);
                //这里的 observer 就是我们通过 addObserver 加入的监听者,它会根据回调的状态和注解去调用对应的方法。
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
            }
        }
    }
}

整个状态的传递如下图所示:

状态传递

最后,让我们用断点验证一下之前的分析,以onResume为例:

onResume 方法的调用过程

4.2 使用 Fragment 的 getLifecycle 注册

下面我们再来分析Fragment的实现过程,Fragment的实现就简单多了,它是直接在对应的生命周期里,通过内部持有的LifecycleRegistry对象调用的,很好理解:

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner {

    void performResume() {
        //简单粗暴,直接通过内部持有的对象调用。
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }
}

之后handleLifecycleEvent的过程就和4.1中一致了,就不过多分析了,大家只需要了解基本的思想就好了,不必过于深究源码。

五、使用 Lifecycle 应该注意什么

https://developer.android.google.cn/topic/libraries/architecture/lifecycle 中提到了下面两点,属于对lifecycle组件的总结,但是很多东西,我们还没有学到,因此先留下原文,等学习完后几章的内容后,再来理解。

5.1 Best practices for lifecycle-aware components

5.2 Use cases for lifecycle-aware components

六、参考文章

(1) Handling lifecycles with lifecycle-aware components
(2) Android 官方架构组件 Lifecycle 详解 & 原理分析
(3) Android 架构组件(一)——Lifecycle

上一篇下一篇

猜你喜欢

热点阅读