《Android编程权威指南》第3版读书笔记 (3) ---fragment中onBackPressed问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gaolh89/article/details/81304808

在《Android编程权威指南》(第3版) 第30章《 网页浏览》30.7 深度学习中,webview多层使用时,按返回键返回上一次网页的问题.

书中只是简单的描述了一下需要重写 Activity.onBackPressed() 方法,但没深入谈论.

一.之前只在Activity中重写过onBackPressed()

之前使用webview时,都是在Activity中,直接重写onBackPressed()方法.本以为fragment中也可以重写改方法,但结果发现并没有此方法.

因为mWebView 控件在Fragment中,不可能将控件传给宿主Activity.然后想着在Fragment定义一个方法,返回 WebView,然后在宿主的 onBackPressed()中 使用这个方法.

代码如下:(Fragment.class)

public WebView goBack() {
        return mWebView;
    }

在宿主Activity.class中

@Override
    public void onBackPressed() {

        WebView webView = PhotoGalleryFragment.newInstance().goBack();
        if (webView.canGoBack()){
            webView.goBack();
        }else {
            super.onBackPressed();
        }

    }

结果直接在Activity中报webview的空指针了.

二.解决方案

(一) 网上的方案:

优雅的让Fragment监听返回键

看过这种方案,是可行的.但是,存在以下几个问题:

1、只适用于一个Activity上只有一个Fragment的情况。
2、只适用于没有Fragment嵌套的情况。

(二)优化
1.同样的先定义一个FragmentBackHandler 接口。

public interface FragmentBackHandler {
    boolean onBackPressed();
}

2.定义一个BackHandlerHelper工具类,用于实现分发back事件,Fragment和Activity的外理逻辑是一样,所以两者都需要调用该类的方法。

public class BackHandlerHelper {
    /**
     * 将back事件分发给 FragmentManager 中管理的子Fragment,如果该 FragmentManager 中的所有Fragment都 * 没有处理back事件,则尝试
     * FragmentManager.popBackStack() * * @return 如果处理了back键则返回 <b>true</b> * @see #handleBackPress
     * (Fragment) * @see #handleBackPress(FragmentActivity)
     */
    public static boolean handleBackPress(FragmentManager fragmentManager) {
        List<Fragment> fragments = fragmentManager.getFragments();
        if (fragments == null) {
            return false;
        }
        for (int i = fragments.size() - 1; i >= 0; i--) {
            Fragment child = fragments.get(i);
            if (isFragmentBackHandled(child)) {
                return true;
            }
        }
        if (fragmentManager.getBackStackEntryCount() > 0) {
            fragmentManager.popBackStack();
            return true;
        }
        return false;
    }

    public static boolean handleBackPress(Fragment fragment) {
        return handleBackPress(fragment.getChildFragmentManager());
    }

    public static boolean handleBackPress(FragmentActivity fragmentActivity) {
        return handleBackPress(fragmentActivity.getSupportFragmentManager());
    }

    /**
     * 判断Fragment是否处理了Back键 * * @return 如果处理了back键则返回 <b>true</b>
     */
    public static boolean isFragmentBackHandled(Fragment fragment) {
        return fragment != null && fragment.isVisible() && fragment.getUserVisibleHint()
                //for ViewPager
                && fragment instanceof FragmentBackHandler && ((FragmentBackHandler)
                fragment).onBackPressed();
    }
}

3.当然 Fragment 也要实现 FragmentBackHandler接口(按需)

public class PhotoGalleryFragment extends Fragment implements FragmentBackHandler {

  //  ....  其他业务代码

   // 重写onBackPressed()方法
    @Override
    public boolean onBackPressed() {
        if (mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        } else {
            return false;
        }
    }

4.宿主Activity覆盖onBackPressed方法(必须)

 @Override
    public void onBackPressed() {
        if (!BackHandlerHelper.handleBackPress(this)) {
            super.onBackPressed();
        }
    }

猜你喜欢

转载自blog.csdn.net/gaolh89/article/details/81304808