如何使活动正确观察生命周期事件



当前,我需要执行一些操作,当

  • 应用程序启动
  • 应用程序已退出
  • 但不是在活动娱乐、配置更改期间

因此,到目前为止,以下代码片段对我非常有用。我从CommonWare的https://commonsware.com/AndroidArch/previews/other-lifecycle-owners和https://proandroiddev.com/react-to-app-foreground-and-background-events-with-processlifecycleowner-96278e5816fa

WeNoteApplication.java

public class WeNoteApplication extends Application {
public static class AppLifecycleObserver implements DefaultLifecycleObserver {
@Override
public void onResume(LifecycleOwner owner) {
// Do something when the application launched.
// But not during activity recreation, configuration change, ...
}
@Override
public void onPause(LifecycleOwner owner) {
// Do something when the application quit.
// But not during activity recreation, configuration change, ...
}
}
private static final AppLifecycleObserver appLifecycleObserver = new AppLifecycleObserver();
@Override
public void onCreate() {
super.onCreate();
initLifecycleObserver();
}
private void initLifecycleObserver() {
Lifecycle lifecycle = ProcessLifecycleOwner.get().getLifecycle();
lifecycle.removeObserver(appLifecycleObserver);
lifecycle.addObserver(appLifecycleObserver);
}
}   

然而,我也需要执行一些操作,通过使用ActivityFragment。。。例如,显示一个DialogFragment

对于我的入口点主Activity,以下是我尝试过的内容。

public class MainActivity extends AppCompatActivity implements DefaultLifecycleObserver {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ProcessLifecycleOwner.get().getLifecycle().removeObserver(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
setContentView(R.layout.activity_main);
}
@Override
public void onResume(LifecycleOwner owner) {
android.util.Log.i("CHEOK", "onResume LifecycleOwner called");
}
@Override
public void onPause(LifecycleOwner owner) {
android.util.Log.i("CHEOK", "onPause LifecycleOwner called");
}
@Override
public void onCreate(LifecycleOwner owner) {
android.util.Log.i("CHEOK", "onCreate LifecycleOwner called");
}
}

由于以下观察,它没有按预期工作

应用程序启动时

onCreate LifecycleOwner called
onResume LifecycleOwner called
onResume LifecycleOwner called    <-- Why onResume of LifecycleOwner is called twice??

当我旋转设备时

onCreate LifecycleOwner called
onResume LifecycleOwner called    <-- Why onCreate and onResume of LifecyclOwner is called during configuration change?

使用LiveData重试

我尝试使用LiveData以便AppLifecycleObserverActivity通信。但是,在配置更改期间,onResumeLiveData将重新创建的Activity视为新的生命周期所有者。因此,它将再次触发它。

public class WeNoteApplication extends Application {
public MutableLiveData<LifecycleOwner> onResumeLiveData = new MutableLiveData<>();
public class AppLifecycleObserver implements DefaultLifecycleObserver {
@Override
public void onResume(LifecycleOwner owner) {
// This will only be called during app launch, not configuration change.
android.util.Log.i("CHEOK", "onResume callback happen in application");
onResumeLiveData.setValue(owner);
...

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WeNoteApplication.instance().onResumeLiveData.observe(this, new Observer<LifecycleOwner>() {
@Override
public void onChanged(@Nullable LifecycleOwner lifecycleOwner) {
// This will only be called during app launch
// This will also be called during configuration change.
android.util.Log.i("CHEOK", "onResume callback happen in activity");
}
});

所以,我有点困惑。Activitly(或Fragment)观察Lifecycle事件的正确方式是什么?也就是说,在配置更改、活动重新创建等过程中,不应该触发这些回调事件函数。。。

我在谷歌的"todo app"项目中找到了它。您可以使用SingleLiveEvent代替MutableLiveData。我希望这对你有帮助。

public class SingleLiveEvent<T> extends MutableLiveData<T> {
private static final String TAG = "SingleLiveEvent";
private final AtomicBoolean mPending = new AtomicBoolean(false);
@MainThread
public void observe(LifecycleOwner owner, final Observer<T> observer) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
}
// Observe the internal MutableLiveData
super.observe(owner, new Observer<T>() {
@Override
public void onChanged(@Nullable T t) {
if (mPending.compareAndSet(true, false)) {
observer.onChanged(t);
}
}
});
}
@MainThread
public void setValue(@Nullable T t) {
mPending.set(true);
super.setValue(t);
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
public void call() {
setValue(null);
}
}

活动生命周期与应用程序生命周期非常不同,如果您使用"活动"的onCreate方法注册观察者,则每次创建活动时都会进行注册-这就是观察结果不正确的原因,即您的活动在配置更改期间被重新创建,导致再次调用onCreate方法,并创建获取事件的新生命周期观察器。

您需要使DefaultLifecycleObserver独立于您的活动。有几种方法可以做到这一点。

  • 我的建议中最好的一个是将AppLifecycleObserver保留在应用程序类中,并向应用程序添加对当前活动的引用。使用此API跟踪应用程序类中的当前活动,将其保存到字段中,并在AppLifecycleObserver回调中使用。但请记住,根据文档中ProcessLifecycleOwner的onPause方法,它将被延迟调用,并且可能没有附加任何活动。

  • 另一种选择是使用广播。将您的AppLifecycleObserver保留在应用程序中,在onResume和onPause方法中发送本地广播,并在活动中收听。使用这种方法,您还可以在服务中收听它,并进行一些后台处理。

问题的根源在LifecycleRegistry.addObserver内部,您可以看到:

void addObserver(生命周期观察者observer)添加一个LifecycleObserver,当生命周期所有者更改状态。

给定的观察者将被带到生命周期所有者。例如,如果LifecycleOwner处于STARTED状态时,给定的观察器将接收ON_CREATE、ON_START事件。

所以让我们看看当您将新的Observer添加到LifeCycleRegistery:时会发生什么

@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
...
State targetState = calculateTargetState(observer);
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
...
}

当您添加新的observer时,LifecycleRegistery会尝试将observer状态带到它自己的状态,在您的情况下,会遍历Activity状态,并且由于该状态是从INITIALIZED开始的,因此注册表调度事件会一直到它的当前状态,即RESUMED:

private State calculateTargetState(LifecycleObserver observer) {
Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);
State siblingState = previous != null ? previous.getValue().mState : null;
State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
: null;
return min(min(mState, siblingState), parentState);
}

TL,DR:因此,当Activity被重新创建时,您看到的重复事件序列(或者当您在第二个活动中注册新的观察者时,您将看到的未来重复事件)实际上来自observer生命周期,也就是Activity生命周期本身!

解决方案将查询进程本身的状态,而不是仅依赖于事件,因此请替换此:

public class MainActivity extends AppCompatActivity implements DefaultLifecycleObserver {
...
@Override
public void onResume(LifecycleOwner owner) {
android.util.Log.i("CHEOK", "onResume LifecycleOwner called");
}
@Override
public void onPause(LifecycleOwner owner) {
android.util.Log.i("CHEOK", "onPause LifecycleOwner called");
}
@Override
public void onCreate(LifecycleOwner owner) {
android.util.Log.i("CHEOK", "onCreate LifecycleOwner called");
}
}

这个:

public class MainActivity extends AppCompatActivity implements DefaultLifecycleObserver {
...
@Override
public void onResume(LifecycleOwner owner) {
if(owner.getLifecycle().getCurrentState() == Lifecycle.State.RESUMED)
android.util.Log.i("CHEOK", "onResume LifecycleOwner called");
}
@Override
public void onPause(LifecycleOwner owner) {
if(owner.getLifecycle().getCurrentState() == Lifecycle.State.STARTED)
android.util.Log.i("CHEOK", "onPause LifecycleOwner called");
}
@Override
public void onCreate(LifecycleOwner owner) {
if(owner.getLifecycle().getCurrentState() == Lifecycle.State.CREATED)
android.util.Log.i("CHEOK", "onCreate LifecycleOwner called");
}
}

解决方案将使用单一的真相来源,如ViewModelApplicationClass,就像您接收LifeCycle.Event一样;现在,如果您计划只执行一次操作,请使用SingleLiveEvent;或者如果您计划在满足条件时在有限的窗口中执行操作,请使用某种总线事件广播

请记住,每次observer注册到LiveData时,都会向其传递最新的值

请通过谷歌查看https://developer.android.com/topic/libraries/architecture/.你将能够在处理生命周期中找到答案。您也可以选择使用视图模型和实时数据

最新更新