最近在練習一個小項目,也就是郭霖大神的開源天氣程序,嘗試用mvp架構加dagger2來重寫了一下,大致功能都實現了,還沒有全部完成。
接近完成的時候,想在天氣信息頁面實現一個很常見的功能,也就是點擊屏幕下方的返回鍵的時候不是返回到上一個activity或者退出,而是提醒用戶再按一次就會退出。
實現思路也很簡單,就是對返回鍵的動作進行監聽和攔截,然后重寫成需要的動作,因為在我的程序中activity只作為調度器使用,真正的View功能在fragment中,所以返回鍵的動作捕捉只能以接口形式寫在BaseActivity中,然后讓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'
本人水平有限,之前很少寫博客,以后會盡量堅持更新,分享學習心得,歡迎交流。