AsyncTask在类中调用另一个函数

时间:2012-11-26 22:45:57

标签: android android-asynctask

基本上,我是否必须将我想要运行的代码放在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()完成,有时不会发生。我很抱歉,如果这已经得到了解答,我试着搜索但是没有找到任何可行的例子,我希望这样做。

4 个答案:

答案 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线程内容