从服务中的线程显示ProgressDialog

时间:2013-10-08 16:54:51

标签: android

我有一个我从MainActivity开始的服务:

    Intent intent = new Intent(getBaseContext(), MyService.class);
    getBaseContext().startService(intent); 

在MyService内部,我创建并启动一个线程,为它提供对服务上下文的引用:

    mThread = new MyThread(this);
    mThread.start();

然后在线程中,我想显示ProgressDialog。我试过这个:

           mProgressDialog = ProgressDialog.show(mContext,
             "", "Receiving file...", true);
             mProgressDialog.show();

但我得到" RuntimeException:无法在未调用Looper.prepare()"的线程内创建处理程序。这是有道理的,所以我尝试了这个:

            HandlerThread progressHandlerThread = new HandlerThread(
                    "ProgressHandlerThread");
            progressHandlerThread.start();

            Handler progressHandler = new Handler(
                    progressHandlerThread.getLooper());
            progressHandler.post(new Runnable()
            {
                @Override
                public void run()
                {
                    mProgressDialog = ProgressDialog.show(mContext, "",
                            "Receiving file...", true);
                    mProgressDialog.show();
                }
            });

但我得到" BadTokenException:无法添加窗口令牌不适用于应用程序"但我不明白这个错误意味着什么。

我见过这个:Show ProgressDialog from thread inside the Service

并且结论似乎是我需要runOnUIThread,但是因为我在服务中,所以我没有引用Activity来执行此操作。任何人都可以解释这个BadTokenException并提出一个很好的方法吗?

3 个答案:

答案 0 :(得分:1)

我认为您尝试直接操作服务UI的事实意味着You're Doing It Wrong™

服务没有UI,因此永远不应直接影响UI。相反,您应该将事件从您的服务传输到侦听活动或片段,例如。

看看https://github.com/square/otto是否有一些非常灵活和有趣的事件。

编辑)看看下面的评论,了解脏问题对David的问题是什么。

答案 1 :(得分:0)

对badTokenException不太了解,但我建议你使用AsyncTask来解决这类问题。您可以在preExecute()方法中启动progressdialog并在postExecute()方法中将其关闭,因为这两者都在UI线程上运行。

答案 2 :(得分:0)

我刚从这里的一个帖子实现了这个。请在页面下方阅读Rachit Mishra的回答,谈论ProgressBar:

Communication between Activity and Service

我的服务中有这个:

public void sendMessage(int state) {
    Message message = Message.obtain();
    switch (state) {
        case 1://SHOW:
            message.arg1 = 1;
            break;
        case 0:
            message.arg1 = 0;
            break;
    }
    try {
        messageHandler.send(message);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

使用1或0调用sendMessage()以显示或关闭服务中的ProgressDialog。

这是我的主要活动:

private ProgressDialog progress;

public class MessageHandler extends Handler {
    @Override
    public void handleMessage(Message message) {
        int state = message.arg1;
        switch (state) {
            case 0://HIDE
                progress.dismiss();
                break;
            case 1://SHOW
                progress = ProgressDialog.show(MainActivity.this, (getResources().getString(R.string.CONNECTING) + "..."), (getResources().getString(R.string.PLEASE_WAIT) + "!"));  //show a progress dialog
                break;
        }
    }
}

无法从服务中显示ProgressDialog,必须从活动或片段中调用它。我希望我添加了您需要的所有代码,并且它可以很好地满足您的需求。说实话,我不确定消息处理程序是如何工作的,但它对我有用!命名可能不是最好的lol。遗憾。