当前,我需要执行一些操作,当
- 应用程序启动
- 应用程序已退出
- 但不是在活动娱乐、配置更改期间
因此,到目前为止,以下代码片段对我非常有用。我从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);
}
}
然而,我也需要执行一些操作,通过使用Activity
、Fragment
。。。例如,显示一个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
以便AppLifecycleObserver
与Activity
通信。但是,在配置更改期间,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");
}
}
,解决方案将使用单一的真相来源,如ViewModel
或ApplicationClass
,就像您接收LifeCycle.Event
一样;现在,如果您计划只执行一次操作,请使用SingleLiveEvent;或者如果您计划在满足条件时在有限的窗口中执行操作,请使用某种总线或事件广播!
请记住,每次observer
注册到LiveData
时,都会向其传递最新的值
请通过谷歌查看https://developer.android.com/topic/libraries/architecture/.你将能够在处理生命周期中找到答案。您也可以选择使用视图模型和实时数据