我有一个运行长任务并返回值的应用程序。任务正在运行时,ProgressDialog
显示进度。任务完成后,我想在TextView
中显示结果。我在FutureTask中运行任务
我的问题是,如果我尝试获取结果,FutureTask的.get()
方法会阻止UI线程,我看不到ProgressDialog
(TextView
显示结果属性)。
我的任务代码(池是ExecutorService):
final FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
@Override
public String call() {
return myLongTask();
}
});
pool.execute(future);
然后我在updateProgressBar()
中拨打Runnable
,用ProgressDialog
更新Handler
:
Runnable pb = new Runnable() {
public void run() {
myUpdateProgressBar();
}
};
pool.execute(pb);
现在我收到的结果会阻止UI线程阻止ProgressDialog
显示:
String result = future.get()
如果我尝试在ProgressDialog解散后将结果放在updateProgressBar()方法内(通过将future作为参数传递),则抛出异常:
只有创建视图层次结构的原始线程才能触及其视图。
任何想法如何解决这个问题? (我听说过AsyncTasks,但我无法弄清楚如何使用它们。)
答案 0 :(得分:2)
您是正确的,您需要AsyncTask
或Thread
/ Handler
组合才能阻止用户界面。
这两种方法都不是很棘手,并且有一些很好的指南可以解释如何做到这一点。以下是我推荐的一些链接。
答案 1 :(得分:0)
是的,我在实现ExecutorService时遇到类似问题,以下代码阻止了UI线程,需要在一个独立的线程上运行:
String result = future.get()
只需创建一个扩展AsyncTask的类来处理future.get()
方法,如下面的代码示例所示:
private class FutureTask extends AsyncTask<Future<String>, Void, String>{
@Override
protected PhotoToView doInBackground(Future<String>... params) {
Future<String> f = params[0];
try {
return f.get(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String futureResult) {
super.onPostExecute(futureResult);
// this method is run on UI thread
// do something with the result
// or simply hide the progress bar
// if you had previously shown one.
}
}
使用以下命令运行未来的主题:
FutureTask ft = new FutureTask();
ft.execute(future);
希望这有帮助。