• 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的操作。

  • 相关阅读:
    猴子选大王(约瑟夫环)
    centos 安装thrift
    KMP字符串匹配算法
    会话技术整理
    PHP数组整理版
    PHP基础知识6【系统内置函数--数组】
    PHP基础知识5【系统内置函数--字符串】
    PHP基础知识笔记4
    PHP基础知识笔记3
    PHP基础知识笔记2
  • 原文地址:https://www.cnblogs.com/muouren/p/12370845.html
Copyright © 2020-2023  润新知