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

Posted

技术标签:

【中文标题】Android:如何将参数传递给 AsyncTask 的 onPreExecute()?【英文标题】:Android: How can I pass parameters to AsyncTask's onPreExecute()? 【发布时间】:2011-03-05 17:42:34 【问题描述】:

我使用AsyncTask 来加载我作为内部类实现的操作。

onPreExecute() 中,我显示了一个加载对话框,然后我再次将其隐藏在onPostExecute() 中。但是对于一些加载操作,我事先知道它们会很快完成,所以我不想显示加载对话框。

我想通过一个可以传递给onPreExecute() 的布尔参数来表明这一点,但显然出于某种原因onPreExecute() 不接受任何参数。

明显的解决方法可能是在我的 AsyncTask 或外部类中创建一个成员字段,我必须在每次加载操作之前设置它,但这似乎不是很优雅。有没有更好的方法来做到这一点?

【问题讨论】:

【参考方案1】:

您可以覆盖构造函数。比如:

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();

【讨论】:

这正是我现在所做的。我仍然需要一个成员变量,但在 AsyncTask 中而不是在外部类中,如果这就是你的意思。这就是我所做的: private class MyAsyncTask extends AsyncTask private boolean showLoading; public MyAsyncTask(boolean showLoading) super(); this.showLoading = 显示加载; // 做事 protected void onPreExecute() if(showLoading) // ... // doInBackground() 等。 是的,就是这么个主意 :) 在 AsynkTask 构造函数中实际上不需要 super()。【参考方案2】:

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) 将方法传递给异步任务 为了避免对异步任务基础结构(线程、消息处理程序、...)进行多次编码,您可以考虑将应该在异步任务中执行的方法作为参数传递。以下示例概述了这种方法。 此外,您可能需要子类化 async-task 以在构造函数中传递初始化参数。

 /* 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;
        
    );     

【讨论】:

【参考方案3】:

为什么、如何以及将哪些参数传递给 Asynctask,详见here。我认为这是最好的解释。

Google 的 android 文档说:

异步任务由 3 个通用类型定义,称为 Params、Progress 和 Result,以及 4 个步骤,称为 onPreExecute、doInBackground、onProgressUpdate 和 onPostExecute。

AsyncTask 的泛型类型:

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

Params,执行时发送给任务的参数类型。 进度,在后台计算期间发布的进度单元的类型。 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) 调用,通常在您想在主屏幕中显示任何进度或信息时使用,例如在后台显示您正在执行的操作进度的进度条。

受保护的 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。方法execute的调用必须在UI Thread中完成。

onPostExecute 方法在 UI Thread 中执行(这里可以调用另一个 AsyncTask!)。

任务的输入参数可以是一个Object数组,这样你就可以放任何你想要的对象和类型。

【讨论】:

【参考方案4】:

您可以在任务构造函数中传递参数,也可以在调用执行时传递:

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);

        
    


【讨论】:

以上是关于Android:如何将参数传递给 AsyncTask 的 onPreExecute()?的主要内容,如果未能解决你的问题,请参考以下文章

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

如何使用底部导航视图和 Android 导航组件将参数传递给片段?

如何将单独的参数传递给 Xamarin Android C# 中的 ListView.ItemClick 调用

Android - 将参数传递给 Android 应用程序中的 RESTful URL

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

将参数传递给回调函数COCOS2D Android