zoukankan      html  css  js  c++  java
  • Android 在fragment中实现返回键单击提醒 双击退出

    尝试用mvp架构加dagger2来重写了一下,大致功能都实现了,还没有全部完成。

    项目地址 

    接近完成的时候,想在天气信息页面实现一个很常见的功能,也就是点击屏幕下方的返回键的时候不是返回到上一个activity或者退出,而是提醒用户再按一次就会退出。

    实现思路也很简单,就是对返回键的动作进行监听和拦截,然后重写成需要的动作,因为在我的程序中activity只作为调度器使用,真正的View功能在fragment中,所以返回键的动作捕捉只能以接口形式

    BaseFragment实现这个接口,代码如下:

       public class BaseActivity extends AppCompatActivity {
        protected final String TAG = this.getClass().getSimpleName();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityCollector.addActivity(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            ActivityCollector.removeActivity(this);
        }
    
        //返回键监听实现
        interface FragmentBackListener {
            void onBackForward();
        }
    
        private FragmentBackListener backListener;
        private boolean isInterception = false;
    
        public void setBackListener(FragmentBackListener backListener) {
            this.backListener = backListener;
        }
        //是否拦截
        public boolean isInterception() {
            return isInterception;
        }
    
        public void setInterception(boolean isInterception) {
            this.isInterception = isInterception;
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (isInterception()) {
                    if (backListener != null) {
                        backListener.onBackForward();
                        return false;
                    }
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    }
    public abstract class BaseFragment extends Fragment implements BaseActivity.FragmentBackListener {
        protected Disposable disposable;
        protected final String TAG = this.getClass().getSimpleName();
        //返回键点击间隔时间计算
        private long exitTime = 0;
    
        //捕捉返回键点击动作
        @Override
        public void onBackForward() {
            //和上次点击返回键的时间间隔
            long intervalTime = System.currentTimeMillis() - exitTime;
            if (intervalTime > 2000) {
                Toast.makeText(getActivity(), getString(R.string.exit_toast), Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                ActivityCollector.finishAll();
            }
        }
    
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            //注册监听
            ((BaseActivity) getActivity()).setBackListener(this);
            ((BaseActivity) getActivity()).setInterception(true);
        }
    
        @Override
        public void onDetach() {
            super.onDetach();
            //取消监听
            ((BaseActivity) getActivity()).setBackListener(null);
            ((BaseActivity) getActivity()).setInterception(false);
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            unsubscribe();
        }
    
        protected void unsubscribe() {
            if (disposable != null && !disposable.isDisposed()) {
                disposable.dispose();
            }
        }
    
    }

    通过一个ActivityCollector来管理活动:

    public class ActivityCollector {
        public static List<Activity> activities = new ArrayList<>();
    
        public static void addActivity(Activity activity) {
            activities.add(activity);
        }
    
        public static void removeActivity(Activity activity) {
            activities.remove(activity);
        }
    
        public static void finishAll() {
            for (Activity activity : activities) {
                if (!activity.isFinishing()) {
                    activity.finish();
                }
            }
        }
    }

    这样,所有继承BaseFragment的fragment都回拥有这个单击提醒 双击退出的功能了,代码不复杂,也带有注释,相信很容易看懂。

    如果某个页面不需要这个功能可以在fragment中重写BaseFragment中的onAttach方法

    @Override
    public void onAttach(Context context) {
           super.onAttach(context);
           ((BaseActivity) getActivity()).setInterception(false);
    }

    当然如果手机应用的大多数页面不需要这个功能,可以在BaseFragment中默认关闭拦截,在需要用的fragment中重写onAttach来打开。

    最后说一点我在开发过程中遇到的小坑,在网络访问的功能方面我使用了squareup的retrofit2和okhttp

    一开始我在build.gradle是这么配置的

        //squareup dependencies
        compile 'com.squareup.okhttp3:okhttp:3.6.0'
        compile 'com.squareup.okio:okio:1.11.0'
        compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
    
        compile 'com.squareup.retrofit2:retrofit:2.2.0'
        compile 'com.squareup.retrofit2:converter-gson:2.2.0'
        compile 'com.squareup.retrofit2:converter-scalars:2.2.0'
        compile 'com.squareup.retrofit2:adapter-rxjava:2.2.0'
    
        //RxJava dependencies
        compile 'io.reactivex.rxjava2:rxandroid:2.0.0'
        compile 'io.reactivex.rxjava2:rxjava:2.0.2'

    但是编译的时候无法通过,

    经过排查,原因是retrofit2自带的rxjava适配器还未升级到rxjava2,所以产生了编译错误,解决办法也不复杂Jake大神给我写了一个rxjava2的适配器,替换原来的就可以了:

        //squareup dependencies
        compile 'com.squareup.okhttp3:okhttp:3.6.0'
        compile 'com.squareup.okio:okio:1.11.0'
        compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
    
        compile 'com.squareup.retrofit2:retrofit:2.2.0'
        compile 'com.squareup.retrofit2:converter-gson:2.2.0' //gson转化器
        compile 'com.squareup.retrofit2:converter-scalars:2.2.0'//String转化器
        compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    
        //RxJava dependencies
        compile 'io.reactivex.rxjava2:rxandroid:2.0.0'
        compile 'io.reactivex.rxjava2:rxjava:2.0.2'
  • 相关阅读:
    1028 List Sorting (25分)
    CSS通用样式类讲解
    异常处理机制
    修饰符及接口和内部类
    用python实现基础的数据类型
    类属性和实例化属性
    命名空间和作用域
    python super()函数有无参数的调用
    编写html页面常常犯的错误
    多态
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7886561.html
Copyright © 2011-2022 走看看