基本上,我是否必须将我想要运行的代码放在doInBackground中的另一个线程上,或者我是否可以在doInBackground中调用另一个函数/类/ what-it-is-functions-are-called-in-JAVA并拥有它异步运行? IE :(我在网上找到的示例代码)
protected String doInBackground(String... params) {
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
return null;
}
是我看到它完成的方式,但我可以这样做:
protected String doInBackground(String... params) {
postToServer(x,y,z,h);
}
并让它调用我已编写的函数,然后让该函数在另一个线程中运行?有时我的HTTP服务器响应有点慢(目前它只是一个低测试服务器),如果我的postToServer()调用时间超过5秒,Android会自动弹出kill进程框,并且还会禁用我的UI直到postToServer()调用完成。这是一个问题,因为我正在开发一个GPS跟踪应用程序(内部为我工作的公司)和UI选项关闭跟踪冻结,直到我的postToServer()完成,有时不会发生。我很抱歉,如果这已经得到了解答,我试着搜索但是没有找到任何可行的例子,我希望这样做。
答案 0 :(得分:3)
您可以这样做,但您必须将UI更新移动到onPostExecute
,因为它在UI线程上运行。
public MyAsyncTask extends AsyncTask<foo, bar, baz> {
...
protected String doInBackground(String... params) {
postToServer(x,y,z,h);
}
protected void onPostExecute(Long result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
}
....
}
您可能希望将TextView传递给AsyncTask
的构造函数,并将其存储为WeakReference。
private final WeakReference textViewReference;
public MyAsyncTask(TextView txt) {
textViewReference = new WeakReference<TextView>(txt);
}
然后在onPostExecute中,您将确保TextView引用仍然存在。
protected void onPostExecute(Long result) {
TextView txt = textViewReference.get();
if (txt != null)
txt.setText("Executed");
}
如果您想通知用户该任务正在执行,我会在调用AsyncTask
之前将其放入。
myTextView.setText("Update in progress...");
new MyAsyncTask().execute();
然后在onPostExecute
中设置TextView
说“更新完成。”
答案 1 :(得分:1)
你有没有尝试过第二种方式?
根据您发布的内容,在第二个示例中,您似乎应该可以正常使用它。
然而(可能与你的问题无关?)在你的第一个例子中我认为它会失败,因为你试图从后台线程更改UI。您希望将操纵TextView的部分放在onPostExecute()
而不是doInBackground()
答案 2 :(得分:1)
是的,你可以调用你的postToServer
方法(这是java中的名字)将在主线程上运行。
doInBackground
AsyncTask
方法中的所有内容都在池化线程上运行,但请确保不要直接调用它!在你的asynktask上调用execute
,android框架将为你完成工作并在另一个线程上运行doInBackground
。
尝试做这样的事情:
new AsyncTask<Void, Void, Void>() {
@Override
// this runs on another thread
protected Void doInBackground(Void... params) {
// assuming x, y, z, h are visible here
postToServer(x, y, z, h);
return null;
}
@Override
// this runs on main thread
protected void onPostExecute(Void result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
}
}.execute(); // call execute, NOT doInBackGround
另请注意,AsyncTask
的所有其他方法(例如onPostExecute
)都在主线程上运行,因此请避免加载它们。
答案 3 :(得分:-1)
最基本的是doInBackground()方法不能与Ui线程或Main线程进行交互。这就是为什么当您尝试与doInBackground()中的TextView交互时,它会导致UI线程崩溃的原因,因为它是非法的。 因此,如果您想与UI线程进行交互,那么在使用doInBackground时,您需要覆盖 OnPostExecute()//完成doInBackground函数作业后,将调用此函数。 因此,当您在doInBackground()中完成工作或在doInBackground()中完成工作时,可以通过此方法更新UI线程内容