在fragment中实现返回键单击提醒 双击退出

最近在练习一个小项目,也就是郭霖大神的开源天气程序,尝试用mvp架构加dagger2来重写了一下,大致功能都实现了,还没有全部完成。

项目地址 

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

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

[java] view plain copy
  1.    public class BaseActivity extends AppCompatActivity {  
  2.     protected final String TAG = this.getClass().getSimpleName();  
  3.   
  4.     @Override  
  5.     protected void onCreate(Bundle savedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         ActivityCollector.addActivity(this);  
  8.     }  
  9.   
  10.     @Override  
  11.     protected void onDestroy() {  
  12.         super.onDestroy();  
  13.         ActivityCollector.removeActivity(this);  
  14.     }  
  15.   
  16.     //返回键监听实现  
  17.     interface FragmentBackListener {  
  18.         void onBackForward();  
  19.     }  
  20.   
  21.     private FragmentBackListener backListener;  
  22.     private boolean isInterception = false;  
  23.   
  24.     public void setBackListener(FragmentBackListener backListener) {  
  25.         this.backListener = backListener;  
  26.     }  
  27.     //是否拦截  
  28.     public boolean isInterception() {  
  29.         return isInterception;  
  30.     }  
  31.   
  32.     public void setInterception(boolean isInterception) {  
  33.         this.isInterception = isInterception;  
  34.     }  
  35.   
  36.     @Override  
  37.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  38.         if (keyCode == KeyEvent.KEYCODE_BACK) {  
  39.             if (isInterception()) {  
  40.                 if (backListener != null) {  
  41.                     backListener.onBackForward();  
  42.                     return false;  
  43.                 }  
  44.             }  
  45.         }  
  46.         return super.onKeyDown(keyCode, event);  
  47.     }  
  48. }  

[java] view plain copy
  1. public abstract class BaseFragment extends Fragment implements BaseActivity.FragmentBackListener {  
  2.     protected Disposable disposable;  
  3.     protected final String TAG = this.getClass().getSimpleName();  
  4.     //返回键点击间隔时间计算  
  5.     private long exitTime = 0;  
  6.   
  7.     //捕捉返回键点击动作  
  8.     @Override  
  9.     public void onBackForward() {  
  10.         //和上次点击返回键的时间间隔  
  11.         long intervalTime = System.currentTimeMillis() - exitTime;  
  12.         if (intervalTime > 2000) {  
  13.             Toast.makeText(getActivity(), getString(R.string.exit_toast), Toast.LENGTH_SHORT).show();  
  14.             exitTime = System.currentTimeMillis();  
  15.         } else {  
  16.             ActivityCollector.finishAll();  
  17.         }  
  18.     }  
  19.   
  20.     @Override  
  21.     public void onAttach(Context context) {  
  22.         super.onAttach(context);  
  23.         //注册监听  
  24.         ((BaseActivity) getActivity()).setBackListener(this);  
  25.         ((BaseActivity) getActivity()).setInterception(true);  
  26.     }  
  27.   
  28.     @Override  
  29.     public void onDetach() {  
  30.         super.onDetach();  
  31.         //取消监听  
  32.         ((BaseActivity) getActivity()).setBackListener(null);  
  33.         ((BaseActivity) getActivity()).setInterception(false);  
  34.     }  
  35.   
  36.     @Override  
  37.     public void onDestroyView() {  
  38.         super.onDestroyView();  
  39.         unsubscribe();  
  40.     }  
  41.   
  42.     protected void unsubscribe() {  
  43.         if (disposable != null && !disposable.isDisposed()) {  
  44.             disposable.dispose();  
  45.         }  
  46.     }  
  47.   
  48. }  
通过一个ActivityCollector来管理活动:
[java] view plain copy
  1. public class ActivityCollector {  
  2.     public static List<Activity> activities = new ArrayList<>();  
  3.   
  4.     public static void addActivity(Activity activity) {  
  5.         activities.add(activity);  
  6.     }  
  7.   
  8.     public static void removeActivity(Activity activity) {  
  9.         activities.remove(activity);  
  10.     }  
  11.   
  12.     public static void finishAll() {  
  13.         for (Activity activity : activities) {  
  14.             if (!activity.isFinishing()) {  
  15.                 activity.finish();  
  16.             }  
  17.         }  
  18.     }  
  19. }  

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

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

[java] view plain copy
  1. @Override  
  2. public void onAttach(Context context) {  
  3.     super.onAttach(context);  
  4.     ((BaseActivity) getActivity()).setInterception(false);  
  5. }  

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

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

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

[html] view plain copy
  1. //squareup dependencies  
  2. compile 'com.squareup.okhttp3:okhttp:3.6.0'  
  3. compile 'com.squareup.okio:okio:1.11.0'  
  4. compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'  
  5.   
  6. compile 'com.squareup.retrofit2:retrofit:2.2.0'  
  7. compile 'com.squareup.retrofit2:converter-gson:2.2.0'  
  8. compile 'com.squareup.retrofit2:converter-scalars:2.2.0'  
  9. compile 'com.squareup.retrofit2:adapter-rxjava:2.2.0'  
  10.   
  11. //RxJava dependencies  
  12. compile 'io.reactivex.rxjava2:rxandroid:2.0.0'  
  13. compile 'io.reactivex.rxjava2:rxjava:2.0.2'  
但是编译的时候无法通过,



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

[html] view plain copy
  1. //squareup dependencies  
  2. compile 'com.squareup.okhttp3:okhttp:3.6.0'  
  3. compile 'com.squareup.okio:okio:1.11.0'  
  4. compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'  
  5.   
  6. compile 'com.squareup.retrofit2:retrofit:2.2.0'  
  7. compile 'com.squareup.retrofit2:converter-gson:2.2.0' //gson转化器  
  8. compile 'com.squareup.retrofit2:converter-scalars:2.2.0'//String转化器  
  9. compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'  
  10.   
  11. //RxJava dependencies  
  12. compile 'io.reactivex.rxjava2:rxandroid:2.0.0'  
  13. compile 'io.reactivex.rxjava2:rxjava:2.0.2'  

本人水平有限,之前很少写博客,以后会尽量坚持更新,分享学习心得,欢迎交流。
 
 
原文地址:https://www.cnblogs.com/lenkevin/p/7614671.html