Android startService()需要很长时间才能返回UI线程
第一次启动时,我的用例(大致)如下:
- 活动启动服务
- 服务获取数据并将其保存在数据库中
- 服务通知具有意图的活动
- 活动显示数据
现在我想在服务繁忙时显示进度条。问题是:
startService(new Intent(getApplicationContext(), UpdateDataService.class));
需要很长时间才能“返回”UI 线程。它似乎是一个同步函数(或者不是?)。如果服务类为空,则 startService 命令几乎会立即处理。看起来 UI 线程等待 Serice 来处理它的工作,这根本没有意义。我尝试启动(尽管看起来很愚蠢)启动异步任务服务,同时在 UI 线程中显示进度条。奇怪的是,有时这会起作用。有时,当我的服务正在运行时,我只会看到白屏,然后是毫秒级的进度条,然后是我的用户界面。
现在我的问题是:如何在不阻塞用户界面的情况下启动服务?
public class MyClass extends TabActivity {
private ProgressDialog pd;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = null;
//building some tabs here, setting some text views....
// starting service if does not exist yet
boolean serviceRunning = false;
final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (final RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if ("aegir.mobile.UpdateDataService".equals(service.service.getClassName())) {
serviceRunning = true;
Log.i(MY_APP_TAG, "Service found.");
}
}
if (!serviceRunning) {
pd = ProgressDialog.show(this, "Loading...", "Setting up data.", true, false);
new StartServiceAsync().execute("");
}
}
private final Handler handler = new Handler() {
@Override
public void handleMessage(final Message msg) {
pd.dismiss();
}
};
public class StartServiceAsync extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(final String... params) {
// starting service
startService(new Intent(getApplicationContext(), UpdateDataService.class));
return null;
}
@Override
protected void onPostExecute(final String result) {
handler.sendEmptyMessage(0);
super.onPostExecute(result);
}
}
my usecase is (roughly) the following on first startup:
- activity starts a service
- service gets and saves data in a database
- service notifies activity with an intent
- activity displays data
Now I want to display a progress bar while the service is busy. The problem is:
startService(new Intent(getApplicationContext(), UpdateDataService.class));
takes a very long time to "come back" to the UI thread. It seems to be a synchronized function (or not?). If a empty the service class the startService command is processed almost instant. It seems the UI thread waits for the Serice to handle its work, which does not make sense at all. I tried to start (as stupid as it may seem) to start the service a async task while displaying a progress bar in my UI thread. Weird enough this works sometimes. Othertimes I just get a white screen while my service is working and afterwards for a millisecond ma progressbar and then my UI.
Now my question: How do I start the service without blocking my UI?
public class MyClass extends TabActivity {
private ProgressDialog pd;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = null;
//building some tabs here, setting some text views....
// starting service if does not exist yet
boolean serviceRunning = false;
final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (final RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if ("aegir.mobile.UpdateDataService".equals(service.service.getClassName())) {
serviceRunning = true;
Log.i(MY_APP_TAG, "Service found.");
}
}
if (!serviceRunning) {
pd = ProgressDialog.show(this, "Loading...", "Setting up data.", true, false);
new StartServiceAsync().execute("");
}
}
private final Handler handler = new Handler() {
@Override
public void handleMessage(final Message msg) {
pd.dismiss();
}
};
public class StartServiceAsync extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(final String... params) {
// starting service
startService(new Intent(getApplicationContext(), UpdateDataService.class));
return null;
}
@Override
protected void onPostExecute(final String result) {
handler.sendEmptyMessage(0);
super.onPostExecute(result);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从指南主题服务:
这不会仅仅因为您从 AsyncTask 调用
startService
而改变。From the guide topic Services:
This doesn't change just because you call
startService
from an AsyncTask.我认为您应该将逻辑从服务移动到异步任务中的 doInBackground 方法。这就是异步任务的用途,执行艰苦的工作,为您提供一种与 UI 交互的简单方法。在异步任务中调用服务很奇怪,你这样做有什么原因吗?
I think you should just move the logic from the service to the doInBackground method in the async task. That's what async task are for, executing hard work giving you a simple way to interact with the UI. It's weird to call a service in the async task, is there any reason why you did that?
要么在
AsyncTask
本身中完成工作,使用IntentService
而不是普通的旧Service
,或者从您的Service< /code> 来完成你的工作。 Android 中的
Service
本身并不使用不同的线程(IntentService
确实可以完成其工作)。尽管从
AsyncTask
启动您的Service
,但现在看来实际工作是在您的 UI 线程中执行的。Either do your work in the
AsyncTask
itself, use anIntentService
instead of a plain oldService
or start a thread from yourService
to do your work. AService
in Android does not inherently use a different thread (IntentService
does to do its work).Despite starting your
Service
from anAsyncTask
, right now it seems the actual work is being performed in your UI thread.请使用此代码以简单的方式执行您所提出的问题。
在服务中,当您的任务完成时调用此方法
please Use this code the easy way to do what you asked in question.
In Service when your Task will Complete call this Method