我有一个我从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并提出一个很好的方法吗?
答案 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。遗憾。