若是咱們的app支持單點登陸、帳戶踢出功能,那麼在接到後端push的「須要踢出當前用戶」的消息後就須要彈出一個dialog。這種dialog出現的時機並不肯定,一種方式就是作一個系統層面的dialog,就像ANR時出現的系統dialog,讓其永遠保持在屏幕的上方。java
Dialog dialog = new Dialog(this);
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
複製代碼
但這種寫法有兩個問題,一個是TYPE_SYSTEM_ALERT
已經被廢棄,其二是須要增長權限。android
/** @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對象:bash
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的方法:app
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()來完成彈窗:ide
((App) getApplication()).showDialog("全局彈窗", "可在任意時機彈出一個dialog")
複製代碼
這裏的代碼在onResume()
和onPause()
作了activity對象的獲取,能夠保證獲取的是當前最上層的activity,當app退出到後臺後這個curActivity
會變爲null,不容許彈出對話框了。最後記得要在彈出時作個activity的判空或isDestroyed()之類的判斷,防止使用了即將銷燬的activity。ui
題外話:this
當你的應用支持了分屏功能,也就是多窗口後,那麼則須要在onStop()中清空activity,在onStart()中獲得activity,更多詳細內容請參考《多窗口支持 | Android Developers》。spa
@Override
public void onActivityStarted(Activity activity) {
curActivity = (AppCompatActivity) activity;
}
@Override
public void onActivityStopped(Activity activity) {
curActivity = null;
}
複製代碼