在Android應用中任意位置執行代碼彈出Dialog有什麼優雅的實現方案?


謝邀。。

方案二你要傳遞的不僅僅是一個Onclicklistener,而是一個方法和它要使用的運行時數據(閉包),這玩意兒一般是沒法序列化的。

你可以使用靜態變數把Listener存內存,然後Activity Dialog要拿回調事件的時候去靜態變數取就行了。如果要允許同時彈多個Dialog的存在,可以用靜態Map存,用時間戳或者什麼的作為Key,開啟Activity Dialog的時候把這個Key放Intent裡面傳過去。(注意內存泄露問題)


不要使用方案一,很明顯這會造成 SDK 代碼 入侵到 App 層,這是在開發 SDK 的時候是需要避免的情況。盡量不要入侵 App 層,外部需要做的工作越少越好。

使用方案二,採用全透明 Activity + 彈出 AlertDialog 的方式,不推薦使用 DialogTheme 這種方式。

下面就是如何解決消息傳遞的問題了:

Plan A. 最直接簡單,使用 LocalBroadcastManager 來廣播 AlertDialog 的事件,比如 Dismiss, OK, Cancel 等,需要處理的就是 AlertDialog 需要一個惟一的 ID(很容易實現全局惟一ID)。需要在合適的時機註冊和反註冊廣播。不需要處理 @weishu 提到的 HashMap 保存 Listener 的問題,不需要 Dialog Activity 過多的關注外界的 HashMap 依賴,但這個方案同樣需要注意註冊廣播如果沒有反註冊導致的內存泄漏風險。

Plan B. 使用 PendingIntent 把需要的數據帶給 Activity,在必要的時候通過廣播發送回來,好處是不再需要全局惟一的 AlertDialog ID。

Plan C. 使用 EventBus 組件替代上面的 Plan A 中的 LocalBroadcastManager。


這個可以考慮在activity的基類中做一些處理。首先定義一個靜態的Queue,然後添加一個方法,功能是獲取當前顯示的activity,顯示一個Dialog,當activity處於onPause和onStop時,直接顯示Dialog,如果是activity已經執行了onStop,則把這個要顯示的內容和listener之類的裝進一個類添加到Queue中,等onPause的時候再一個個poll出來執行,無論是activity恢復或者finish進入下一個activity都會執行到onPause。

但這個做法對於SDK還是不太好,而且有內存泄漏的風險,最好不要給這些Dialog設置用戶實現的Listener,可以用EventBus或廣播來發送和接收這些Dialog的事件。。。


方案二絕對是可行的.本人的APP就是採用方案二,Listener事件完全無非就是Activity之間通信的問題.使用樓下說的事件匯流排可以辦到,自己實現類似於監聽的方式也可以做到


Activity的消息回調還有種方法使用messager, 現在的項目中就是使用的messager。

-----------
/**
* 回調Intent
*/
public class CallbackIntent extends Intent {
 ...............................................
/**
* 設置回調
* @param callback
*/
public void setCallback(final Callback callback) {
if (Looper.myLooper() == null) {
Looper.prepare();
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
callback.onResult(msg.obj);
}
}; 
Messenger messenger = new Messenger(handler);
putExtra(INTENT_DATA_MESSAGER, messenger);

}

/**
* 通知回調數據
* @param data
*/
public static void onCallback(Intent intent, Object data) {
if (intent == null) {
return;
}
Messenger messenger = intent.getParcelableExtra(INTENT_DATA_MESSAGER);
if (messenger == null) {
return;
}

Message message = new Message();
message.obj = data;
try {
messenger.send(message);
} catch(Exception e) {
Log.e(TAG, "send callback message failed", e);
}
}

public interface Callback{
void onResult(Object result);
}
}
-------------------------------------------------------------------------------

--------------------------調用方式--------------------------

CallbackIntent intent = new CallbackIntent(getContext(), AlertDialogActivity.class);
intent.setCallback(new CallbackIntent.Callback() {
@Override
public void onResult(Object result) {
//  這裡執行
AlertDialogActivity返回的結果
}
});

還有,在AlertDialogActivity結束時,需要執行

--------------------------AlertDialogActivity.class-------------------------

public void onOK() {

  CallbackIntent.onCallback(getIntent(), result);

  finish();


最好不要自己彈dialog,因為你dialog的樣式會給其他人造成困擾,發個通知就好了。


為什麼不用windowmanager.addView方式實現全局的dialog?


使用方案二,把onClick事件封裝好用事件匯流排傳回來即可


我使用的activity形式

想傳listener?封裝進一個bean啊,啟動activity的時候 傳入就好。。。。


推薦閱讀:

Android Framework 如何學習,如何從應用深入到Framework?
想買一本安卓的教程書,什麼樣的比較好?
各位 Android 開發者們現在用的是什麼主力手機?
android view的繪製中,View繪製的時間如何和vsync屏幕刷新頻率保持同步的?
android開發,你們還在findviewbyid嗎?

TAG:Android開發 | Android |