Jetpack Navigation 系列
navigation 导航返回操作系列问题和源代码解读文章目录
前言
Navigation这个组件第一次使用到实际项目中,在项目中遇到问题, 下面问题的记录。以及涉及到的系统源代码提示:以下是本篇文章正文内容,下面案例可供参考
一: 系统back按钮处理流程处理
Activity中的流程。
- Activity–>KeyDown–>
- if (keyCode == KeyEvent.KEYCODE_BACK)–> onBackPressed();
- 下面代码说明返回按钮的处理顺序。 mActionBar->Fragment-> Activity自身
- Activity自身的默认行为是关闭掉自己 (finish())
public void onBackPressed() {
if (mActionBar != null && mActionBar.collapseActionView()) {
return;
}
FragmentManager fragmentManager = mFragments.getFragmentManager();
if (!fragmentManager.isStateSaved() &&
fragmentManager.popBackStackImmediate()) {
return;
}
if (!isTaskRoot()) {
// If the activity is not the root of the task,
// allow finish to proceed normally.
finishAfterTransition();
return;
}
try {
// Inform activity task manager that
// the activity received a back press
// while at the root of the task.
// This call allows ActivityTaskManager
// to intercept or defer finishing.
ActivityTaskManager.getService().onBackPressedOnTaskRoot(mToken,
new IRequestFinishCallback.Stub() {
public void requestFinish() {
mHandler.post(() -> finishAfterTransition());
}
});
} catch (RemoteException e) {
finishAfterTransition();
}
}
在ComponentActivity中处理流程。
- androidx.activity.ComponentActivity.onBackPressed
- AndroidX中重写了对BackPressed事件的处理方式。
- 这里是我们今天的重点OnBackPressedDispatcher
- 代码重点结论。
后显示的页面,先处理返回事件。
OnBackPressedCallback ,可以开启和关闭当前注册的事件回调处理器
如果没有如何OnBackPressedCallback了,那么做Activity的callback
//-------------------
//类名 androidx.activity.ComponentActivity.java
public void onBackPressed() {
mOnBackPressedDispatcher.onBackPressed();
}
private final OnBackPressedDispatcher mOnBackPressedDispatcher =
new OnBackPressedDispatcher(new Runnable() {
@Override
public void run() {
ComponentActivity.super.onBackPressed();
}
});
public final OnBackPressedDispatcher getOnBackPressedDispatcher() {
return mOnBackPressedDispatcher;
}
//OnBackPressedDispatcher.java
@MainThread
public void onBackPressed() {
//后入栈的,先处理返回事件
Iterator<OnBackPressedCallback> iterator =
mOnBackPressedCallbacks.descendingIterator();
//
while (iterator.hasNext()) {
OnBackPressedCallback callback = iterator.next();
if (callback.isEnabled()) {
callback.handleOnBackPressed();
return;
}
}
if (mFallbackOnBackPressed != null) {
mFallbackOnBackPressed.run();
}
}
```java
@Nullable
private final Runnable mFallbackOnBackPressed;
@SuppressWarnings("WeakerAccess") /* synthetic access */
final ArrayDeque<OnBackPressedCallback> mOnBackPressedCallbacks = new ArrayDeque<>();
NavHostFragment 系统返回按钮的处理流程。
> NavHostFragment->onCreate->NavHostController->setOnBackPressedDispatche
> NavHostFragment->onCreate->NavHostController->enableOnBackPressed
> 这里的enableOnBackPressed和R.styleable.NavHostFragment_defaultNavHost的是关联在一起的。
> 如果defaultNavHost设置为false。那么默认是不会按下返回按键就关闭当前目标Fragment的。
//androidx.navigation.fragmen.NavHostFragment
public void onCreate(@Nullable Bundle savedInstanceState) {
mNavController.setOnBackPressedDispatcher(requireActivity().getOnBackPressedDispatcher());
mNavController.enableOnBackPressed(
mIsPrimaryBeforeOnCreate != null
&& mIsPrimaryBeforeOnCreate);
mIsPrimaryBeforeOnCreate = null;
}
public void onInflate(@NonNull Context context, @NonNull AttributeSet attrs,
@Nullable Bundle savedInstanceState) {
super.onInflate(context, attrs, savedInstanceState);
final TypedArray navHost = context.obtainStyledAttributes(attrs,
androidx.navigation.R.styleable.NavHost);
final int graphId = navHost.getResourceId(androidx.navigation.R.styleable.NavHost_navGraph, 0);
if (graphId != 0) {
mGraphId = graphId;
}
navHost.recycle();
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NavHostFragment);
final boolean defaultHost = a.getBoolean(R.styleable.NavHostFragment_defaultNavHost, false);
if (defaultHost) {
mDefaultNavHost = true;
}
a.recycle();
}
//NavHostController
@Override
public final void setOnBackPressedDispatcher(@NonNull OnBackPressedDispatcher dispatcher) {
super.setOnBackPressedDispatcher(dispatcher);
}
@Override
public final void enableOnBackPressed(boolean enabled) {
super.enableOnBackPressed(enabled);
}
//NavController
//开启回调
private void updateOnBackPressedCallbackEnabled() {
mOnBackPressedCallback.setEnabled(mEnableOnBackPressedCallback
&& getDestinationCountOnBackStack() > 1);
}
//注册mOnBackPressedCallback到ComponentActivity的mOnBackPressedDispatcher中。
void setOnBackPressedDispatcher(@NonNull OnBackPressedDispatcher dispatcher) {
...
// Remove the callback from any previous dispatcher
mOnBackPressedCallback.remove();
// Then add it to the new dispatcher
dispatcher.addCallback(mLifecycleOwner, mOnBackPressedCallback);
}
//默认返回按钮是,NavController中的mOnBackPressedCallback会执行出栈操作。
private final OnBackPressedCallback mOnBackPressedCallback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
popBackStack();
}
};
二 OnBackPressedDispatcher
- 系统实现的观察这设计模式。
- 添加OnBackPressedCallback对象到ArrayDeque
- 从ArrayDeque中删除OnBackPressedCallback
- 通知队列中的观察者对象事件发生了。
- 代码解析
- 状态判断,LifecycleOwner 是否已经DESTROYED,是则return
- addCancellable(LifecycleOnBackPressedCancellable)
- LifecycleOnBackPressedCancellable 对象创建。
//androidx.activity.OnBackPressedDispatcher
public void addCallback(@NonNull LifecycleOwner owner,
OnBackPressedCallback onBackPressedCallback) {
Lifecycle lifecycle = owner.getLifecycle();
if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {
return;
}
onBackPressedCallback.addCancellable(
new LifecycleOnBackPressedCancellable(lifecycle, onBackPressedCallback));
}
Cancellable addCancellableCallback(@NonNull OnBackPressedCallback onBackPressedCallback) {
mOnBackPressedCallbacks.add(onBackPressedCallback);
OnBackPressedCancellable cancellable =
new OnBackPressedCancellable(onBackPressedCallback);
onBackPressedCallback.addCancellable(cancellable);
return cancellable;
}
//androidx.activity.ComponentActivity.java
@Override
@MainThread
public void onBackPressed() {
mOnBackPressedDispatcher.onBackPressed();
}
//androidx.activity.OnBackPressedDispatcher
@MainThread
public void onBackPressed() {
Iterator<OnBackPressedCallback> iterator =
mOnBackPressedCallbacks.descendingIterator();
while (iterator.hasNext()) {
OnBackPressedCallback callback = iterator.next();
if (callback.isEnabled()) {
callback.handleOnBackPressed();
return;
}
}
if (mFallbackOnBackPressed != null) {
mFallbackOnBackPressed.run();
}
}
private class LifecycleOnBackPressedCancellable
implements LifecycleEventObserver,
Cancellable {
private final Lifecycle mLifecycle;
private final OnBackPressedCallback mOnBackPressedCallback;
@Nullable
private Cancellable mCurrentCancellable;
LifecycleOnBackPressedCancellable(@NonNull Lifecycle lifecycle,
@NonNull OnBackPressedCallback onBackPressedCallback) {
mLifecycle = lifecycle;
mOnBackPressedCallback = onBackPressedCallback;
lifecycle.addObserver(this);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_START) {
mCurrentCancellable = addCancellableCallback(mOnBackPressedCallback);
} else if (event == Lifecycle.Event.ON_STOP) {
// Should always be non-null
if (mCurrentCancellable != null) {
mCurrentCancellable.cancel();
}
} else if (event == Lifecycle.Event.ON_DESTROY) {
cancel();
}
}
@Override
public void cancel() {
mLifecycle.removeObserver(this);
mOnBackPressedCallback.removeCancellable(this);
if (mCurrentCancellable != null) {
mCurrentCancellable.cancel();
mCurrentCancellable = null;
}
}
}
总结
看完了,先解决一下问题,下周继续更新。