完美實現賬戶踢出時的全域性彈窗

天之界線2010發表於2019-03-04

完美實現賬戶踢出時的全域性彈窗

如果我們的app支援單點登入、賬戶踢出功能,那麼在接到後端push的“需要踢出當前使用者”的訊息後就需要彈出一個dialog。這種dialog出現的時機並不確定,一種方式就是做一個系統層面的dialog,就像ANR時出現的系統dialog,讓其永遠保持在螢幕的上方。

Dialog dialog = new Dialog(this);
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
複製程式碼

但這種寫法有兩個問題,一個是TYPE_SYSTEM_ALERT已經被廢棄,其二是需要增加許可權。

/** @deprecated */
@Deprecated
public static final int TYPE_SYSTEM_ALERT = 2003;
複製程式碼
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
複製程式碼

我們可以換個思路來考慮這個需求,要知道dialog的構建和activity是強相關的,解決方案是永遠儲存當前的activity物件,當鎖屏和app退出到後臺時,清空儲存的當前activity。

首先,在application中持有當前的activity物件:

public class App extends Application {

    private AppCompatActivity curActivity;

    @Override
    public void onCreate() {
        super.onCreate();
        
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityResumed(Activity activity) {
                curActivity = (AppCompatActivity) activity;
            }

            @Override
            public void onActivityPaused(Activity activity) {
                curActivity = null;
            }
        });
    }
}
複製程式碼

然後,定義彈出dialog的方法:

public class App extends Application {

    private AppCompatActivity curActivity;

    public void showDialog(String title, String message) {
        if (curActivity == null) {
            return; // 不要忘了判空操作
        }
        
        EasyDialog.builder(curActivity)
                .setTitle(title)
                .setMessage(message)
                .setPositiveButton("ok", null)
                .build()
                .show(curActivity.getSupportFragmentManager());
    }
}
複製程式碼

最後,在需要的時候呼叫application中的showDialog()來完成彈窗:

((App) getApplication()).showDialog("全域性彈窗", "可在任意時機彈出一個dialog")
複製程式碼

這裡的程式碼在onResume()onPause()做了activity物件的獲取,可以保證獲取的是當前最上層的activity,當app退出到後臺後這個curActivity會變為null,不允許彈出對話方塊了。最後記得要在彈出時做個activity的判空或isDestroyed()之類的判斷,防止使用了即將銷燬的activity。

題外話:

完美實現賬戶踢出時的全域性彈窗

當你的應用支援了分屏功能,也就是多視窗後,那麼則需要在onStop()中清空activity,在onStart()中得到activity,更多詳細內容請參考《多視窗支援  |  Android Developers》

@Override
public void onActivityStarted(Activity activity) {
    curActivity = (AppCompatActivity) activity;
}

@Override
public void onActivityStopped(Activity activity) {
    curActivity = null;
}
複製程式碼

聯絡作者

完美實現賬戶踢出時的全域性彈窗

相關文章