Android:如何将参数传递给 AsyncTask 的 onPreExecute()?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3075009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: How can I pass parameters to AsyncTask's onPreExecute()?
提问by Steven Meliopoulos
I use an AsyncTask
for loading operations that I implemented as an inner class.
我使用一个AsyncTask
作为内部类实现的加载操作。
In onPreExecute()
I show a loading dialog which I then hide again in onPostExecute()
. But for some of the loading operations I know in advance that they will finish very quickly so I don't want to display the loading dialog.
在onPreExecute()
我显示一个加载对话框,然后我再次隐藏在onPostExecute()
. 但是对于一些加载操作,我事先知道它们会很快完成,所以我不想显示加载对话框。
I wanted to indicate this by a boolean parameter that I could pass to onPreExecute()
but apparently for some reason onPreExecute()
doesn't take any parameters.
我想通过一个布尔参数来表明这一点,我可以传递给它,onPreExecute()
但显然由于某种原因onPreExecute()
不接受任何参数。
The obvious workaround would probably be to create a member field in my AsyncTask or in the outer class which I would have to set before every loading operation but that does not seem very elegant. Is there a better way to do this?
显而易见的解决方法可能是在我的 AsyncTask 或外部类中创建一个成员字段,我必须在每次加载操作之前设置它,但这似乎不太优雅。有一个更好的方法吗?
回答by Felix
You can override the constructor. Something like:
您可以覆盖构造函数。就像是:
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
public MyAsyncTask(boolean showLoading) {
super();
// do stuff
}
// doInBackground() et al.
}
Then, when calling the task, do something like:
然后,在调用任务时,执行以下操作:
new MyAsyncTask(true).execute(maybe_other_params);
Edit:this is more useful than creating member variables because it simplifies the task invocation. Compare the code above with:
编辑:这比创建成员变量更有用,因为它简化了任务调用。将上面的代码与:
MyAsyncTask task = new MyAsyncTask();
task.showLoading = false;
task.execute();
回答by Karl
1) For me that's the most simple way passing parametersto async task is like this
1)对我来说,将参数传递给异步任务的最简单方法是这样的
// To call the async task do it like this
Boolean[] myTaskParams = { true, true, true };
myAsyncTask = new myAsyncTask ().execute(myTaskParams);
Declare and use the async task like here
像这里一样声明并使用异步任务
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) Passing methods to async-taskIn order to avoid coding the async-Task infrastructure (thread, messagenhandler, ...) multiple times you might consider to pass the methods which should be executed in your async-task as a parameter. Following example outlines this approach. In addition you might have the need to subclass the async-task to pass initialization parameters in the constructor.
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;
}
});
}
回答by Naveed Jamali
why, how and which parameters are passed to Asynctask<>, see detail here. I think it is the best explanation.
为什么,如何以及哪些参数传递给 Asynctask<>,请参阅此处的详细信息。我认为这是最好的解释。
Google's Android Documentation Says that :
谷歌的 Android 文档说:
An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
异步任务由 3 个泛型类型(称为 Params、Progress 和 Result)和 4 个步骤(称为 onPreExecute、doInBackground、onProgressUpdate 和 onPostExecute)定义。
AsyncTask's generic types :
AsyncTask 的通用类型:
The three types used by an asynchronous task are the following:
异步任务使用的三种类型如下:
Params, the type of the parameters sent to the task upon execution. Progress, the type of the progress units published during the background computation. Result, the type of the result of the background computation. Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:
参数,执行时发送到任务的参数类型。Progress,后台计算期间发布的进度单元的类型。结果,后台计算结果的类型。并非所有类型总是由异步任务使用。要将类型标记为未使用,只需使用类型 Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
You Can further refer : http://developer.android.com/reference/android/os/AsyncTask.html
您可以进一步参考:http: //developer.android.com/reference/android/os/AsyncTask.html
Or You Can clear whats the role of AsyncTask by refering Sankar-Ganesh's Blog
或者你可以通过参考 Sankar-Ganesh 的博客来明确 AsyncTask 的作用
Well The structure of a typical AsyncTask class goes like :
那么典型的 AsyncTask 类的结构如下:
private class MyTask extends AsyncTask<X, Y, Z>
protected void onPreExecute(){
}
This method is executed before starting the new Thread. There is no input/output values, so just initialize variables or whatever you think you need to do.
此方法在启动新线程之前执行。没有输入/输出值,因此只需初始化变量或您认为需要执行的任何操作。
protected Z doInBackground(X...x){
}
The most important method in the AsyncTask class. You have to place here all the stuff you want to do in the background, in a different thread from the main one. Here we have as an input value an array of objects from the type “X” (Do you see in the header? We have “...extends AsyncTask” These are the TYPES of the input parameters) and returns an object from the type “Z”.
AsyncTask 类中最重要的方法。你必须把你想做的所有事情都放在后台,放在与主线程不同的线程中。这里我们有一个来自“X”类型的对象数组作为输入值(你在标题中看到了吗?我们有“...extends AsyncTask”这些是输入参数的类型)并从类型返回一个对象“Z”。
protected void onProgressUpdate(Y y){
受保护的无效 onProgressUpdate(Y y){
} This method is called using the method publishProgress(y) and it is usually used when you want to show any progress or information in the main screen, like a progress bar showing the progress of the operation you are doing in the background.
此方法使用方法 publishProgress(y) 调用,通常用于在主屏幕中显示任何进度或信息时,例如在后台显示正在执行的操作进度的进度条。
protected void onPostExecute(Z z){
protected void onPostExecute(Z z){
} This method is called after the operation in the background is done. As an input parameter you will receive the output parameter of the doInBackground method.
} 这个方法是在后台操作完成后调用的。作为输入参数,您将收到 doInBackground 方法的输出参数。
What about the X, Y and Z types?
X、Y 和 Z 类型呢?
As you can deduce from the above structure:
从上面的结构可以推导出:
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.
How do we call this task from an outside class? Just with the following two lines:
我们如何从外部课程中调用此任务?只需以下两行:
MyTask myTask = new MyTask();
myTask.execute(x);
Where x is the input parameter of the type X.
其中 x 是类型 X 的输入参数。
Once we have our task running, we can find out its status from “outside”. Using the “getStatus()” method.
一旦我们的任务运行起来,我们就可以从“外部”找到它的状态。使用“getStatus()”方法。
myTask.getStatus(); and we can receive the following status:
myTask.getStatus(); 我们可以收到以下状态:
RUNNING - Indicates that the task is running.
RUNNING - 表示任务正在运行。
PENDING - Indicates that the task has not been executed yet.
PENDING - 表示任务尚未执行。
FINISHED - Indicates that onPostExecute(Z) has finished.
FINISHED - 表示 onPostExecute(Z) 已经完成。
Hints about using AsyncTask
关于使用 AsyncTask 的提示
Do not call the methods onPreExecute, doInBackground and onPostExecute manually. This is automatically done by the system.
不要手动调用 onPreExecute、doInBackground 和 onPostExecute 方法。这是由系统自动完成的。
You cannot call an AsyncTask inside another AsyncTask or Thread. The call of the method execute must be done in the UI Thread.
您不能在另一个 AsyncTask 或线程中调用 AsyncTask。方法 execute 的调用必须在 UI 线程中完成。
The method onPostExecute is executed in the UI Thread (here you can call another AsyncTask!).
onPostExecute 方法在 UI 线程中执行(这里可以调用另一个 AsyncTask!)。
The input parameters of the task can be an Object array, this way you can put whatever objects and types you want.
任务的输入参数可以是一个 Object 数组,这样你就可以放入任何你想要的对象和类型。
回答by live-love
You can either pass the parameter in the task constructor or when you call execute:
您可以在任务构造函数中或在调用执行时传递参数:
AsyncTask<Object, Void, MyTaskResult>
The first parameter (Object) is passed in doInBackground. The third parameter (MyTaskResult) is returned by doInBackground. You can change them to the types you want. The three dots mean that zero or more objects (or an array of them) may be passed as the argument(s).
在 doInBackground 中传递第一个参数 (Object)。第三个参数 (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);
}
}
}