Fragment_3_Androidx中返回键的处理

在Fragment中处理返回键操作

在新版的AndroidX之前,我们想要自定义处理返回键操作,必须得在activity和fragment中自己实现。

而在新版的AndroidX的Fragment相关组件中,加入了可以自定义处理后退按钮的操作,

getActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) {
    @Override
    public void handleOnBackPressed() {
        xxxx
    }
});

有两个addCallback:

@MainThread
public void addCallback(@NonNull LifecycleOwner owner, @NonNull OnBackPressedCallback onBackPressedCallback) 
@MainThread
public void addCallback(@NonNull OnBackPressedCallback onBackPressedCallback)

区别在于,

  • l 有LifecycleOwner的会根据lifecycle自动的添加和删除callback,
  • l 而第二个删除时需要手动调用OnBackPressedCallback.remove(),

源码分析

具体就是在ComponentActivity中:

/**
 * Called when the activity has detected the user's press of the back
 * key. The {@link #getOnBackPressedDispatcher() OnBackPressedDispatcher} will be given a
 * chance to handle the back button before the default behavior of
 * {@link android.app.Activity#onBackPressed()} is invoked.
 *
 * @see #getOnBackPressedDispatcher()
 */
@Override
@MainThread
public void onBackPressed() {
    mOnBackPressedDispatcher.onBackPressed();
}

/**
 * Retrieve the {@link OnBackPressedDispatcher} that will be triggered when {@link #onBackPressed()} is called.
 * @return The {@link OnBackPressedDispatcher} associated with this ComponentActivity.
 */
@NonNull
@Override
public final OnBackPressedDispatcher getOnBackPressedDispatcher() {
    return mOnBackPressedDispatcher;
}

OnBackPressedDispatcher.onBackPressed()

/**
触发对当前添加的OnBackPressedCallback的调用,调用的顺序与添加它们的顺序相反。
只有最近添加的OnBackPressedCallback未启用时,才会调用以前添加的回调。
强烈建议在调用此方法之前调用hasEnabledCallbacks(),以确定在调用此方法时此方法是否会触发任何已启用的回调。
 */
@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();
    }
}

而mFallbackOnBackPressed是指当没有OnBackPressedCallback时进行的操作,

在ComponentActivity中创建OnBackPressedDispatcher时传递了这个mFallbackOnBackPressed:

private final OnBackPressedDispatcher mOnBackPressedDispatcher =
        new OnBackPressedDispatcher(new Runnable() {
            @Override
            public void run() {
                ComponentActivity.super.onBackPressed();
            }
        });

也就是调用activity的onBackPressed。

OnBackPressedCallback

public abstract class OnBackPressedCallback {
    private boolean mEnabled;

    public OnBackPressedCallback(boolean enabled) {
        mEnabled = enabled;
    }

    /**
     * Set the enabled state of the callback. Only when this callback
     * is enabled will it receive callbacks to {@link #handleOnBackPressed()}.
     * <p>
     * Note that the enabled state is an additional layer on top of the
     * {@link androidx.lifecycle.LifecycleOwner} passed to
     * {@link OnBackPressedDispatcher#addCallback(LifecycleOwner, OnBackPressedCallback)}
     * which controls when the callback is added and removed to the dispatcher.
     *
     * @param enabled whether the callback should be considered enabled
     */
    @MainThread
    public final void setEnabled(boolean enabled) {
        mEnabled = enabled;
    }

    /**
     * Checks whether this callback should be considered enabled. Only when this callback
     * is enabled will it receive callbacks to {@link #handleOnBackPressed()}.
     *
     * @return Whether this callback should be considered enabled.
     */
    @MainThread
    public final boolean isEnabled() {
        return mEnabled;
    }

   /**
    * Removes this callback from any {@link OnBackPressedDispatcher} it is currently
    * added to.
    */
   @MainThread
   public final void remove() {
       for (Cancellable cancellable: mCancellables) {
           cancellable.cancel();
       }
   }


    /**
     * Callback for handling the {@link OnBackPressedDispatcher#onBackPressed()} event.
     */
    @MainThread
    public abstract void handleOnBackPressed();

}

OnBackPressedDispatcher

public OnBackPressedDispatcher(@Nullable Runnable fallbackOnBackPressed) {
    mFallbackOnBackPressed = fallbackOnBackPressed;
}

@MainThread
public void addCallback(@NonNull OnBackPressedCallback onBackPressedCallback) {
    addCancellableCallback(onBackPressedCallback);
}

@MainThread
@NonNull
Cancellable addCancellableCallback(@NonNull OnBackPressedCallback onBackPressedCallback) {
    mOnBackPressedCallbacks.add(onBackPressedCallback);
    OnBackPressedCancellable cancellable = new OnBackPressedCancellable(onBackPressedCallback);
    onBackPressedCallback.addCancellable(cancellable);
    return cancellable;
}

@MainThread
public void addCallback(@NonNull LifecycleOwner owner,
        @NonNull OnBackPressedCallback onBackPressedCallback) {
    Lifecycle lifecycle = owner.getLifecycle();
    if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {
        return;
    }

    onBackPressedCallback.addCancellable(
            new LifecycleOnBackPressedCancellable(lifecycle, onBackPressedCallback));
}

@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 OnBackPressedCancellable implements Cancellable {
    private final OnBackPressedCallback mOnBackPressedCallback;
    OnBackPressedCancellable(OnBackPressedCallback onBackPressedCallback) {
        mOnBackPressedCallback = onBackPressedCallback;
    }

    @Override
    public void cancel() {
        mOnBackPressedCallbacks.remove(mOnBackPressedCallback);
        mOnBackPressedCallback.removeCancellable(this);
    }
}

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;
        }
    }
}

为什么要手动删除callback时需要调用OnBackPressedCallback.remove()?

因为addCallback里会把OnBackPressedCallback进行一个封装(OnBackPressedCancellable/LifecycleOnBackPressedCancellable ),然后加入到了OnBackPressedCallback中,

当调用OnBackPressedCallback.remove()时就会去调用封装的cancel方法,而在cancel中有删除callback的操作。

原文地址:https://www.cnblogs.com/muouren/p/12370845.html