Android: 我该如何将参数传递给AsyncTask的onPreExecute()方法?

118
我使用一个内部类实现的AsyncTask来进行加载操作。在onPreExecute()中,我显示一个加载对话框,然后在onPostExecute()中隐藏它。但是,对于某些加载操作,我事先知道它们将非常快地完成,所以我不想显示加载对话框。
我希望通过一个布尔参数来指示这一点,我可以将其传递给onPreExecute(),但很明显由于某些原因,onPreExecute()没有接受任何参数的选项。
明显的解决方法可能是在我的AsyncTask或外部类中创建一个成员字段,在每次加载操作之前必须设置该字段,但这似乎不太优雅。有更好的方法吗?
4个回答

238

您可以覆盖构造函数,例如:

private class MyAsyncTask extends AsyncTask<Void, Void, Void> {

    public MyAsyncTask(boolean showLoading) {
        super();
        // do stuff
    }

    // doInBackground() et al.
}

然后,在调用该任务时,做如下操作:

new MyAsyncTask(true).execute(maybe_other_params);

编辑: 这比创建成员变量更有用,因为它简化了任务调用。将上面的代码与以下代码进行比较:


MyAsyncTask task = new MyAsyncTask();
task.showLoading = false;
task.execute();

3
这正是我现在所做的。我仍然需要一个成员变量,但如果您的意思是要将其放在AsyncTask而不是外部类中,那么就是这样。这就是我所做的:private class MyAsyncTask extends AsyncTask<Void, Void, Void> { private boolean showLoading; public MyAsyncTask(boolean showLoading) { super(); this.showLoading = showLoading; // 做一些事情 } protected void onPreExecute(){ if(showLoading){ // ... } } // doInBackground() 等等 } - Steven Meliopoulos
1
是的,那基本上就是我的想法 :) - Felix
1
在AsynkTask构造函数中实际上不需要super()。 - ostergaard

65

1) 对于我来说,将参数传递给异步任务最简单的方式就是这样:

// To call the async task do it like this
Boolean[] myTaskParams = { true, true, true };
myAsyncTask = new myAsyncTask ().execute(myTaskParams);

像这样声明和使用异步任务

private class myAsyncTask extends AsyncTask<Boolean, Void, Void> {

    @Override
    protected Void doInBackground(Boolean...pParams) 
    {
        Boolean param1, param2, param3;

        //

          param1=pParams[0];    
          param2=pParams[1];
          param3=pParams[2];    
      ....
}                           

2)将方法传递给异步任务 为了避免多次编写异步任务基础架构(线程、消息处理程序等),您可以考虑将应在异步任务中执行的方法作为参数传递。以下示例概述了这种方法。 此外,您可能需要子类化异步任务以在构造函数中传递初始化参数。

 /* Generic Async Task    */
interface MyGenericMethod {
    int execute(String param);
}

protected class testtask extends AsyncTask<MyGenericMethod, Void, Void>
{
    public String mParam;                           // member variable to parameterize the function
    @Override
    protected Void doInBackground(MyGenericMethod... params) {
        //  do something here
        params[0].execute("Myparameter");
        return null;
    }       
}

// to start the asynctask do something like that
public void startAsyncTask()
{
    // 
    AsyncTask<MyGenericMethod, Void, Void>  mytest = new testtask().execute(new MyGenericMethod() {
        public int execute(String param) {
            //body
            return 1;
        }
    });     
}

11

如何以及为什么要向Asynctask<>传递哪些参数?详见这里。我认为这是最好的解释。

Google的Android文档说:

异步任务由三个通用类型Params,Progress和Result定义,并由四个步骤onPreExecute、doInBackground、onProgressUpdate和onPostExecute组成。

AsyncTask的通用类型:

异步任务使用的三种类型如下:

Params:在执行任务时发送到任务的参数类型。 Progress:在后台计算期间发布的进度单元的类型。 Result:后台计算结果的类型。 并非所有类型都总是被异步任务使用。若要将类型标记为未使用,只需使用Void类型即可:

 private class MyTask extends AsyncTask<Void, Void, Void> { ... }

您可以进一步参考:http://developer.android.com/reference/android/os/AsyncTask.html

或者,您可以通过参考Sankar-Ganesh的博客来了解AsyncTask的作用。

一个典型的AsyncTask类的结构如下:

private class MyTask extends AsyncTask<X, Y, Z>

    protected void onPreExecute(){ 

    } 

在启动新线程之前执行此方法。没有输入/输出值,因此只需初始化变量或您认为需要执行的任何操作。

protected Z doInBackground(X...x){

}
AsyncTask类中最重要的方法。您必须在此处放置想要在后台中执行的所有内容,并且在与主线程不同的线程中执行。这里我们的输入值是“X”类型的对象数组(在标题中看到了吗?我们有“...extends AsyncTask”这些是输入参数的类型),返回值为“Z”类型的对象。

protected void onProgressUpdate(Y y){

} 使用publishProgress(y)方法调用此方法,并且通常在您希望在主屏幕上显示任何进度或信息时使用,例如显示进度条以显示您在后台执行的操作的进度。

protected void onPostExecute(Z z){

} 此方法在后台操作完成后调用。作为输入参数,您将收到doInBackground方法的输出参数。

X、Y和Z类型如何处理?

正如您可以从上面的结构推断出的那样:

X – The type of the input variables value you want to set to the background process. This can be an array of objects.

 Y – The type of the objects you are going to enter in the onProgressUpdate method.

 Z – The type of the result from the operations you have done in the background process.
我们如何从外部类调用此任务?只需使用以下两行代码:
MyTask myTask = new MyTask();

myTask.execute(x);

其中x是类型为X的输入参数。

一旦我们的任务开始运行,我们可以从“外部”了解其状态。使用“getStatus()”方法。

myTask.getStatus(); 然后我们就可以收到以下状态:

RUNNING - 表示任务正在运行。

PENDING - 表示任务尚未执行。

FINISHED - 表示onPostExecute(Z)已经完成。

关于使用AsyncTask的提示

不要手动调用onPreExecute、doInBackground和onPostExecute方法,这些方法会被系统自动执行。

不能在另一个AsyncTask或线程中调用AsyncTask。必须在UI线程中调用execute方法。

方法onPostExecute在UI线程中执行(在此可以调用另一个AsyncTask!)。

任务的输入参数可以是对象数组,这样您可以放置任何对象和类型。


5
你可以通过任务构造函数或在调用执行时传递参数:
AsyncTask<Object, Void, MyTaskResult>

第一个参数(Object)在doInBackground中传递。第三个参数(MyTaskResult)由doInBackground返回。您可以将它们更改为所需的类型。三个点表示可以作为参数传递零个或多个对象(或它们的数组)。

public class MyActivity extends AppCompatActivity {

    TextView textView1;
    TextView textView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);    
        textView1 = (TextView) findViewById(R.id.textView1);
        textView2 = (TextView) findViewById(R.id.textView2);

        String input1 = "test";
        boolean input2 = true;
        int input3 = 100;
        long input4 = 100000000;

        new MyTask(input3, input4).execute(input1, input2);
    }

    private class MyTaskResult {
        String text1;
        String text2;
    }

    private class MyTask extends AsyncTask<Object, Void, MyTaskResult> {
        private String val1;
        private boolean val2;
        private int val3;
        private long val4;


        public MyTask(int in3, long in4) {
            this.val3 = in3;
            this.val4 = in4;

            // Do something ...
        }

        protected void onPreExecute() {
            // Do something ...
        }

        @Override
        protected MyTaskResult doInBackground(Object... params) {
            MyTaskResult res = new MyTaskResult();
            val1 = (String) params[0];
            val2 = (boolean) params[1];

            //Do some lengthy operation    
            res.text1 = RunProc1(val1);
            res.text2 = RunProc2(val2);

            return res;
        }

        @Override
        protected void onPostExecute(MyTaskResult res) {
            textView1.setText(res.text1);
            textView2.setText(res.text2);

        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接