1. 程式人生 > >Android 在fragment中實現返回鍵單擊提醒 雙擊退出

Android 在fragment中實現返回鍵單擊提醒 雙擊退出

make listener 一次 time lean 適配器 == sea dagger2

嘗試用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

Android 在fragment中實現返回鍵單擊提醒 雙擊退出