1、问题背景:
场景如下:在页面 activity A 中点击一个按钮后会出现一个弹框 dialog,dialog 中有个列表,点击列表中的 item, 进入到页面 activity B,再从 activity B 返回 到 activity A 时,列表需要刷新一下(实际需求中,每次 dialog 重新可见时(如跳转后返回、切后台、屏幕解锁等)都需刷新列表)。
问题分解一下,即弹框需要感知 activity A 的 onResume()
生命周期方法。那么,实现这种需求,可以有如下方法:
2、 解决方法
方法1:广播或者 EventBus
在 activity A 的 onResume()
方法中发出广播或事件,dialog 接收到广播时做刷新动作。
该方法能实现上述需求,但不够优雅,广播或者事件总线是零碎、没有中心的,太多的广播或者事件总线给人一种狗皮膏药的感觉,哪里有毛病就往哪贴,导致项目容易踩坑,出了问题也不好追根溯源。
方法2:Lifecycle
该解决方案也是最终使用的方法。
谷歌官方推出 Lifecycle 就是为了方便、优雅地处理组件生命周期的问题。我们先看如何实现前面所说的场景。
首先,需要感知生命周期的弹框需要实现LifecycleObserver
接口,作为观察者角色来观察生命周期的变化
import android.app.Activity;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.PopupWindow;
import java.lang.ref.WeakReference;
public class LifecycleWindow extends PopupWindow implements LifecycleObserver {
private WeakReference<Window> mParentWindow;
public LifecycleWindow(Activity activity) {
super(activity);
View contentView = LayoutInflater.from(activity).inflate(R.layout.layout_lifecycle_window, null);
setContentView(contentView);
mParentWindow = new WeakReference<>(activity.getWindow());
}
public void popupFromBottom() {
if (mParentWindow.get() != null) {
showAtLocation(mParentWindow.get().getDecorView(), Gravity.BOTTOM, 0, 0);
}
}
/**
* LifeCycleActivityA生命周期走到 onResume()时,会触发下面方法
*/
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume() {
if (isShowing()) {
// TODO: 2019-11-22 refresh
}
LogUtils.e("test", "LifecycleWindow onResume " + isShowing());
}
}
activity A 的代码如下:
public class LifecycleActivityA extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//activity_life_cycle.xml 中只有一个 ID 为 tv_lifecycle 的按钮
setContentView(R.layout.activity_life_cycle);
findViewById(R.id.tv_lifecycle).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// LifecycleActivityB 为测试的空页面
startActivity(new Intent(LifecycleActivityA.this, LifecycleActivityB.class));
}
});
getLifecycle().addObserver(new LifecycleWindow(this));
}
}
只需要在 activity A 中加入 getLifecycle().addObserver(new LifecycleWindow(this));
,将要LifecycleWindow
添加为观察者,LifecycleWindow
即可感知 LifecycleActivityA
生命周期的变化。
3、其他应用场景
同样,Lifecycle
还有很多可能的应用场景。下面再列举两种:
比如,可以让 定位组件 感知生命周期,即让页面在onResume
时开始定位,在onDestory
时停止定位,那么也可以在 定位组件 manager 中做上述类似LifecycleWindow
的处理,让其实现 LifecycleObserver
,这样定位组件也拥有了生命周期。
还有,可以感知生命周期 Banner 或 Adapter。例如多类型 itemView 的 RecycleView 中存在轮播 Banner,还有其他 item。如果让 adapter 实现 LifecycleObserver
,就可以在页面onResume
时就开始 Banner 的轮播,在onPause
或 onDestory
的时候暂停 banner 的轮播。这样就可以避免出现跳转到其他页面后 Banner 还在轮播的情况,Banner 的曝光统计也会更加精确。
4、Lifecycle 原理:
下面跟踪下源码,看看Lifecycle
是如何可以做到感知生命周期变化的。
先看几个相关的类:
Lifecycle
:描述生命周期的抽象类;LifecycleOwner
:持有Lifecycle,连接有生命周期的对象,AppCompactActivity 和 ActivityFragment 都实现了该接口,可以提供一个Lifecycle对象。相当于是被观察者。LifecycleObserver
:通过实现该接口,观察LifecycleOwner的生命周期变化。相当于是观察者。State
: Lifecycle 内部枚举。标识当前生命周期所处状态Event
: Lifecycle 内部枚举。标识当前生命周期改变对应的事件。当 Lifecycle 生命周期改变,如进入 onCreate, 会自动触发 ON_CREATE 事件。
public abstract class Lifecycle {
//注册LifecycleObserver (如前面的Window)
@MainThread
public abstract void addObserver(@NonNull LifecycleObserver observer);
@MainThread
public abstract void removeObserver(@NonNull LifecycleObserver observer);
@MainThread
@NonNull
public abstract State getCurrentState();
public enum Event {
ON_CREATE,
ON_START,
ON_RESUME,
ON_PAUSE,
ON_STOP,
ON_DESTROY,
ON_ANY
}
public enum State {
DESTROYED,
INITIALIZED,
CREATED,
STARTED,
RESUMED;
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0;
}
}
}
以 Activity 为例。查看源码发现,AppCompatActivity 继承自 FragmentActivity,FragmentActivity 继承自 ComponentActivity,而ComponentActivity implements LifecycleOwner,在 ComponentActivity 的 onCreate() 中,有如下一行:
`ReportFragment.injectIfNeededIn(this);`
ReportFragment 就负责监听 ComponentActivity 生命周期的变化:
//note:有删除一些无关紧要的代码
public class ReportFragment extends Fragment {
public static void injectIfNeededIn(Activity activity) {
android.app.FragmentManager manager = activity.getFragmentManager();
}
static ReportFragment get(Activity activity) {
return (ReportFragment) activity.getFragmentManager().findFragmentByTag(
REPORT_FRAGMENT_TAG);
}
private ActivityInitializationListener mProcessListener;
private void dispatchCreate(ActivityInitializationListener listener) {
if (listener != null) {
listener.onCreate();
}
}
private void dispatchStart(ActivityInitializationListener listener) {
if (listener != null) {
listener.onStart();
}
}
private void dispatchResume(ActivityInitializationListener listener) {
if (listener != null) {
listener.onResume();
}
}
@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 onDestroy() {
super.onDestroy();
dispatch(Lifecycle.Event.ON_DESTROY);
// just want to be sure that we won't leak reference to an activity
mProcessListener = null;
}
private void dispatch(Lifecycle.Event event) {
Activity activity = getActivity();
if (activity instanceof LifecycleRegistryOwner) {
((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
return;
}
if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
}
void setProcessListener(ActivityInitializationListener processListener) {
mProcessListener = processListener;
}
interface ActivityInitializationListener {
void onCreate();
void onStart();
void onResume();
}
}
上面,当生命周期改变时,会走到 dispatch()
方法中,而 dispatch()
最终会走到 LifecycleRegistry 的 handleLifecycleEvent()
。
// androidx.lifecycle#LifecycleRegistry
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event);
moveToState(next);
}
//获取 “即将的事件” :当前事件执行后,即将会处于什么事件
static State getStateAfter(Event event) {
switch (event) {
case ON_CREATE:
case ON_STOP:
return CREATED;
case ON_START:
case ON_PAUSE:
return STARTED;
case ON_RESUME:
return RESUMED;
case ON_DESTROY:
return DESTROYED;
case ON_ANY:
break;
}
throw new IllegalArgumentException("Unexpected event value " + event);
}
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();
while (!isSynced()) {
mNewEventOccurred = false;
if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
backwardPass(lifecycleOwner);
}
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
sync()
会根据当前状态 mState 与 mObserverMap 中的 eldest 和 newest 的状态进行对比 ,判断当前状态是向前还是向后。如由 STARTED 到 RESUMED 是状态向前,反之向后。以向前为例:
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.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
popParentState();
}
}
}
从上面可以看, handleLifecycleEvent()
会通过 getStateAfter ()
获取当前应处的状态并修改 Lifecycle 本身的状态 State 值,然后遍历所有 LifecycleObserver 并同步且通知其状态发生变化,因此就能触发LifecycleObserver 对应的生命周期事件。