我使用AsyncTask来改变TextView的文本,如下所示:
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
response += url;
}
return response;
}
@Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
如果我在OnClick事件中调用它,一切都会好的:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = (TextView) findViewById(R.id.txt);
Button button = (Button)this.findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new LongOperation().execute(new String[]{"Hello"});
}
});
}
但问题是当我在我的帖子中调用它时,程序被强制关闭
this.closeButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Thread t= new Thread(){
@Override
public void run(){
try{
//Do something
//Then call AsyncTask
new LongOperation().execute(new String[]{"Hello"});
}catch(Exception e){}
}
};
t.start();
}
});
我哪里错了?我不明白差异如何在线程中调用AsyncTask。
答案 0 :(得分:8)
我建议您咨询AsyncTask documentation和Processes and Threads,以便更好地了解其工作原理。基本上,您应该在主线程上创建AsyncTask子类。
当您致电AsyncTask.execute()时,您在主线程上调用了您提供的AsyncTask.onPreExecute,因此您可以进行UI设置。
调用下一个AsyncTask.doInBackground方法,并在其自己的线程中运行。
最后,当您的AsyncTask.doInBackground方法完成时,会在主线程上调用AsyncTask.onPostExecute,您可以进行任何UI清理。
如果您需要在AsyncTask.doInBackground方法中更新用户界面,请拨打AsyncTask.publishProgress,这将在主线程中调用onProgressUpdate。
答案 1 :(得分:2)
当您从UI线程调用它时,关联的Context
正在运行Activity
。当您从常规线程调用它时,没有与该线程关联的有效Context
。 AsyncTask
在自己的线程中执行,你不应该创建自己的线程。如果那是实际代码,那么你就会误解AsyncTask
的观点。搜索有关如何使用它的教程。
答案 2 :(得分:1)
添加其他人所说的内容:我认为您可以使用AsyncTask在另一个线程中启动任务,即使您从不同于UI的线程启动AsyncTask也是如此。
但是在这种情况下,唯一的方法是你只能间接修改UI,例如:以某种方式将当前Activity的处理程序传递给此AsyncTask实例,并向其发送消息(处理程序消息得到处理) UI线程)。或者使用活动捕获的广播意图并相应地更新UI等。但这些解决方案似乎有些过度。