你怎么能传递多个原始参数到AsyncTask?

有相关的问题,比如我如何将2个parameter passing给一个AsyncTask类? ,但我碰到了徒劳地试图将多个原语作为parameter passing给AsyncTask的困难,所以我想分享我发现的东西。 这个微妙的东西在现有的问题和答案中并没有被体现出来,所以我想帮助那些和我一样遇到同样问题的人,并帮他们解决痛苦。

问题是这样的:我有多个原始参数(例如两个长),我想传递给一个AsyncTask在后台执行 – 怎么可以做? (我的答案…经过一段时间的努力…可以在下面find。)

只需将你的原语包装在一个简单的容器中,并将其作为parameter passing给AsyncTask,就像这样:

private static class MyTaskParams { int foo; long bar; double arple; MyTaskParams(int foo, long bar, double arple) { this.foo = foo; this.bar = bar; this.arple = arple; } } private class MyTask extends AsyncTask<MyTaskParams, Void, Void> { @Override protected void doInBackground(MyTaskParams... params) { int foo = params[0].foo; long bar = params[0].bar; double arple = params[0].arple; ... } } 

像这样调用它:

 MyTaskParams params = new MyTaskParams(foo, bar, arple); MyTask myTask = new MyTask(); myTask.execute(params); 

(严格来说)不可能将多个基元传递给AsyncTask。 例如,如果要执行myTask.execute(long1, long2)并尝试设置private class myTask extends AsyncTask<long, Void, Void> ,则使用相应的方法private class myTask extends AsyncTask<long, Void, Void>

 @Override protected LocationItemizedOverlay doInBackground(long... params) {...} 

您的IDE可能会抱怨需要重写超types方法。 请注意,您正在使用doInBackground所谓的Varargs方法签名,其中(long... params)就像是说“我接受一个可变数量的long,存储为一个名为params的数组,我不完全明白是什么原因一个编译器/ IDE的投诉将被提出,但我认为这与如何定义generics类Params

在任何情况下,只要你正确地将你的原语转换为它们各自的非原始包装(例如int => Integer,long => Long等等),就可以实现你想要的没有问题的东西。 实际上,你不需要明确地把你的原语转换成非原语。 Java似乎为你处理。 你只需要如下设置你的ASyncTask(以长整型为例):

 private class MyTask extends AsyncTask<Long, Void, Void> { @Override protected void doInBackground(Long... params) { // Do stuff with params, for example: long myFirstParam = params[0] } ... } 

然后,您可以按照您的初衷使用此课程,例如:

 MyTask myTask = new MyTask(); myTask.execute(long1, long2); 

或者对于任何你想要的原语,提供它们都是相同的types。 如果你需要传递多种types的原语,也可以这样做,但是你需要修改上面的内容到:

 private class MyTask extends AsyncTask<Object, Void, Void> { @Override protected void doInBackground(Object... params) { // Do stuff with params, for example: long myLongParam = (Long) params[0]; int myIntParam = (Integer) params[1]; } ... } 

这更加灵活,但它需要明确地将参数转换为它们各自的types。 如果不需要这种灵活性(即单一数据types),我build议坚持第一个选项,因为它的可读性略高。

另一种方法:您只需要在MyTask类中添加MyTask构造函数:

 private class MyTask extends AsyncTask<String, Void, Void> { int foo; long bar; double arple; MyTask(int foo, long bar, double arple) { // list all the parameters like in normal class define this.foo = foo; this.bar = bar; this.arple = arple; } ...... // Here is doInBackground etc. as you did before } 

然后打电话

 new MyTask(int foo, long bar, double arple).execute(); 

第二种方式像David Wasser的答案。

我喜欢马拉基思的方法,但是如果你不这样做,难道你不能用Bundle类吗?

  Bundle myBundle = new Bundle(); myBundle.putInt("foo", foo); myBundle.putLong("bar", bar); myBundle.putDouble("arple", arple); 

然后只需传递该包并将其解包到MyTask中。 这是一个可怕的主意吗? 您避免创build一个自定义类,如果您决定稍后需要传递其他参数,则会很灵活。

这是通过子类来解决的。 Google在官方的Android AsyncTask文档中有一个解决这个问题(子类)的例子:

http://developer.android.com/reference/android/os/AsyncTask.html

例:

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }