从后台线程弹出Android对话框

9
我需要一个弹出式对话框在我从不同的线程接收到消息时显示出来,但是该对话框不应依赖于Activity,即它应该在屏幕焦点所在的任何地方显示。
这可以实现吗?因为对话框是按Activity处理的,所以我考虑使用一个服务,但又会增加一个线程,而我想避免这种情况。
还有其他选项可供选择吗?

我相信他试图问的是:如何从在单独线程中运行的服务启动对话框?可能有多个活动正在运行。要显示对话框,您需要指定当前活动。 - Edward Anderson
一个可能的解决方案是使用一个活动: http://stackoverflow.com/posts/3912748/revisions - user2020854
https://stackoverflow.com/a/29804684/2149195 - RBK
3个回答

17
如果您想问如何在用户手机上的活动不是焦点活动时显示对话框,则可以尝试使用通知而不是弹出对话框,因为在其他应用程序上弹出对话框会打断用户可能正在进行的其他操作。根据Android用户界面指南

使用通知系统——不要使用对话框代替通知

如果您的后台服务需要通知用户,请使用标准通知系统——不要使用对话框或toast通知用户。对话框或toast会立即接管焦点并打断用户,将焦点从他们正在做的事情上转移走:当对话框出现时,用户可能正在输入文本,并且可能会意外地对对话框采取行动。用户习惯于处理通知,并可以在方便的时候下拉通知栏以回复您的消息。

创建通知的指南在这里:http://developer.android.com/guide/topics/ui/notifiers/notifications.html

你好, 在 iPhone 中,有一个应用程序委托(Application delegate)始终监听 UI 更改,那么在 Android 中是否有类似的东西呢? - Sam97305421562
Facebook Messenger(Bubbles)不遵循这个规则... - sospedra
@Bursos,我不确定你的观点是什么。Facebook经常不遵循Android UI指南。此外,这些气泡不会像对话框那样接管用户输入。 - Intrications
@Intrications 或许我错了,但我认为 Facebook 的那些对话框不遵守通知-对话框模式,因为当有人与您交谈时,应该是通知而不是弹出对话框(确认是否要查看对话)。我只是想指出像 Facebook 这样的大公司并不总是遵循主要的 Android 规则。 - sospedra

1
如果我理解正确,您可以为所有活动使用一个基类。
public abstract class BaseActivity extends Activity{
    protected static BaseActivity current_context = null;

    @override
    protected void onPause(){
        current_context = null;
        super.onPause();
    }

    @override
    protected void onResume(){
        current_context = this;
        super.onResume();
    }

    public static void showDialog(/*your parameters*/){
        //show nothing, if no activity has focus
        if(current_context == null)return;
        current_context.runOnUiThread(new Runnable() {
            @override
            public void run(){
                AlertDialog.Builder builder = 
                    new AlertDialog.Builder(current_context);
                //your dialog initialization
                builder.show();
            }
        });
    }
}

在您的线程中展示您与BaseActivity.showDialog(..)的对话。但是,如果您想在目标设备的任何活动上方展示您的对话框,则此方法不起作用。


1

替代方案:

AlertDialog dialog;
//add this to your code
    dialog = builder.create();
    Window window = dialog.getWindow(); 
    WindowManager.LayoutParams lp = window.getAttributes();
    lp.token = mInputView.getWindowToken();
    lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    window.setAttributes(lp);
    window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
//end addons
alert.show();

1
那么...你认为我在后台线程中能从哪里获取mInputView呢? ;) - Janusz
(new AlertDialog.Builder(myAppContext)).create() 给我回了 java.lang.RuntimeException: 不能在没有调用 Looper.prepare() 的线程中创建 Handler。 - Jeno Csupor
你应该使用活动上下文而不是应用程序上下文。 - 7heViking
这行代码表示什么意思?lp.token = mInputView.getWindowToken();我们需要一个视图来获取token吗?如果是,我们需要一个活动上下文! - C--

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接