如何将多个原始参数传递给AsyncTask?

rob*_*ess 77 primitive android variadic-functions android-asynctask

有相关的问题,例如如何将2个参数传递给AsyncTask类?但是我遇到了徒劳地尝试将多个原语作为参数传递给AsyncTask的困难,所以我想分享我发现的东西.在现有的问题和答案中没有捕捉到这种微妙之处,所以我想帮助那些遇到与我一样的问题的人,并为他们省去痛苦.

问题是:我有多个原始参数(例如两个long),我想传递给AsyncTask以在后台执行 - 它怎么能完成?(我的回答......经过一段时间的挣扎......可以在下面找到.)

Dav*_*ser 149

只需将基元包装在一个简单的容器中,然后将其作为参数传递给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;
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样称呼它:

MyTaskParams params = new MyTaskParams(foo, bar, arple);
MyTask myTask = new MyTask();
myTask.execute(params);
Run Code Online (Sandbox Code Playgroud)

  • 实际上这让我感觉好多了.我一直在使用Object ... params这样做的方式,并且由于某种原因它只是感觉不好或不安全. (10认同)
  • 非常优雅,喜欢它. (2认同)
  • @DavidWasser :感谢您的更新,除了给定的解决方案效果很好! (2认同)

mal*_*isi 90

另一种方法:您只需要在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
}
Run Code Online (Sandbox Code Playgroud)

然后打电话

new MyTask(int foo, long bar, double arple).execute();
Run Code Online (Sandbox Code Playgroud)

第二种方式,如David Wasser的答案.

  • 实际上,这是我最喜欢的三种传递不同类型参数的方式.没有要转换的对象,也不需要创建其他类. (9认同)
  • 你需要在重写的构造函数中调用super()! (3认同)
  • @zyamys为什么在这里需要super()?据我了解,它将被自动调用。看到这里http://stackoverflow.com/a/2054040/984263 (2认同)

rob*_*ess 79

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

@Override
protected LocationItemizedOverlay doInBackground(long... params) {...}
Run Code Online (Sandbox Code Playgroud)

您的IDE可能会抱怨需要覆盖超类型方法.请注意,您正在使用所谓的Varargs方法签名doInBackground,其中(long... params)说"我接受可变数量的long,存储为名为params的数组.我不完全理解导致编译器/ IDE投诉的原因,但我认为它与泛型类Params的定义有关.

在任何情况下,只要您正确地将基元转换为各自的非原始包装器(例如int => Integer,long => Long等),就可以毫无问题地实现您想要的功能.实际上,您不需要将基元显式转换为非基元.Java似乎为你处理这个问题.您只需要按如下方式设置ASyncTask(例如longs):

private class MyTask extends AsyncTask<Long, Void, Void> {

    @Override
    protected void doInBackground(Long... params) {
        // Do stuff with params, for example:
        long myFirstParam = params[0]
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以按照最初的预期使用此类,例如:

MyTask myTask = new MyTask();
myTask.execute(long1, long2);
Run Code Online (Sandbox Code Playgroud)

或者对于你想要的任何数量的原语,提供它们是相同类型的.如果您需要传递多种类型的基元,也可以这样做,但您需要将上述内容修改为:

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

    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

这更灵活,但需要将参数明确地转换为各自的类型.如果不需要这种灵活性(即单一数据类型),我建议坚持使用第一个选项,因为它更具可读性.


MrP*_*low 7

我喜欢malajisi的方法,但如果你没有,你不能使用Bundle类吗?

 Bundle myBundle = new Bundle();
 myBundle.putInt("foo", foo);
 myBundle.putLong("bar", bar);
 myBundle.putDouble("arple", arple);
Run Code Online (Sandbox Code Playgroud)

然后只需传递捆绑包并将其解压缩到MyTask中.这是一个糟糕的主意吗?您可以避免创建自定义类,如果您决定稍后需要传递其他参数,则它很灵活.


Spe*_*pgh 7

内置的execute方法接受数组的Params,但是它们都必须是已定义的类型..因此,如果您只是将PARAM类型设置为OBJECT,那么只要它们是对象的子对象,就可以传入任何内容。 ...

private class MyTask extends AsyncTask<Object, Void, Void> {
Run Code Online (Sandbox Code Playgroud)

然后在doInBackGround中,只需将每个参数转换为所需的参数即可:

 @Override
 protected void doInBackground(Object... params) {
     Context t = (Context)params[0];
     String a = (String) params[1];
     List<LatLng> list = (List<LatLng>)params[2];
     .
     .
     .
Run Code Online (Sandbox Code Playgroud)

您的执行过程很简单:

 new MyTask().execute(context,somestring,list_of_points);
Run Code Online (Sandbox Code Playgroud)

不如将其包装在您自己的包装器类,bundle,hash之类的形式中那样好,因为您的订单依赖于双方,但是它可以工作。当然,您可以只将数组作为HashMap(,)的参数,并且基本上可以自定义实现捆绑包,但是它将起作用。