你怎么能传递多个原始参数到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"); } }