Есть связанные вопросы, например, Как передать 2 параметра классу AsyncTask? , но я столкнулся с трудностями, пытаясь безуспешно пытаться передать несколько примитивов в качестве параметров в AsyncTask, поэтому я хочу поделиться тем, что я обнаружил. Эта тонкость не отражена в существующих вопросах и ответах, поэтому я хочу помочь всем, кто столкнется с той же проблемой, что и я, и избавить их от боли.
Вопрос в следующем: у меня есть несколько примитивных параметров (например, два long), которые я хочу передать в AsyncTask для выполнения в фоновом режиме - как это можно сделать? (Мой ответ ... после некоторой борьбы с этим ... можно найти ниже.)
android
android-asynctask
primitive
variadic-functions
робгиннесс
источник
источник
Ответы:
Просто оберните свои примитивы в простой контейнер и передайте его в качестве параметра
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);
источник
Другой способ: вам просто нужно добавить конструктор 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();
Второй способ, подобный ответу Дэвида Вассера.
источник
<(String,Object,int),Void,Void>
(Строго говоря) НЕ возможно передать несколько примитивов в AsyncTask. Например, если вы хотите выполнить
myTask.execute(long1, long2)
и попробовать настроитьprivate class myTask extends AsyncTask<long, Void, Void>
с помощью соответствующего метода:@Override protected LocationItemizedOverlay doInBackground(long... params) {...}
ваша IDE, скорее всего, будет жаловаться на необходимость переопределения метода супертипа. Обратите внимание, что вы используете так называемую сигнатуру метода Varargs для
doInBackground
, где(long... params)
это все равно что сказать: «Я принимаю переменное количество long, хранящееся в виде массива с именем params. Я не совсем понимаю, что вызывает жалобу компилятора / IDE. , но я думаю, это связано с тем, как общий классParams
.В любом случае можно без проблем достичь желаемого, при условии, что вы правильно приведете свои примитивы к их соответствующим непримитивным оболочкам (например, int => Integer, long => Long и т. Д.). На самом деле, вам не нужно явно приводить примитивы к не примитивам. Кажется, Java справится с этим за вас. Вам просто нужно настроить ASyncTask следующим образом (на примере long):
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);
Или для любого количества примитивов, которое вы хотите, ПРИ условии, что они одного типа. Если вам нужно передать несколько типов примитивов, это также можно сделать, но вам нужно будет изменить приведенное выше, чтобы:
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]; } ... }
Это более гибкий вариант, но требует явного приведения параметров к соответствующим типам. Если такая гибкость не требуется (например, один тип данных), я рекомендую придерживаться первого варианта, так как он немного более читабелен.
источник
protected LocationItemizedOverlay doInBackground(Object[] objects)
и добавить следующее для определения асинхронной задачи.private class MyTask extends AsyncTask<Object, Void, Void>
Встроенный метод execute принимает массив Params , но все они должны быть определенного типа ... поэтому, если вы просто установите тип PARAM на OBJECT , вы можете передать все, что захотите, если они являются дочерними объектами. ...
private class MyTask extends AsyncTask<Object, Void, Void> {
Затем в вашем doInBackGround вы просто приводите каждый параметр, чтобы вернуться к тому, что вам нужно:
@Override protected void doInBackground(Object... params) { Context t = (Context)params[0]; String a = (String) params[1]; List<LatLng> list = (List<LatLng>)params[2]; . . .
И ваше исполнение просто:
new MyTask().execute(context,somestring,list_of_points);
Не такая хорошая форма, как упаковка в ваш собственный класс-оболочку, или пакет, или хэш, или что-то в этом роде, потому что вы зависимы от порядка с обеих сторон, но это будет работать. Конечно, вы можете просто сделать свой массив параметром HashMap (,), и вы в основном настраиваете реализацию пакета на этом этапе, но это будет работать.
источник
Мне нравится метод Маладжиси, но если нет, не могли бы вы использовать класс Bundle?
Bundle myBundle = new Bundle(); myBundle.putInt("foo", foo); myBundle.putLong("bar", bar); myBundle.putDouble("arple", arple);
Затем просто передайте пакет и распакуйте его в MyTask. Это ужасная идея? Вы избегаете создания настраиваемого класса, и он гибок, если вы решите, что вам нужно будет передать дополнительные параметры позже.
Обновление: прошло довольно много лет с тех пор, как я написал этот ответ, и мне он действительно не нравится сейчас. Я бы не рекомендовал использовать Bundle. Если вам нужно передать несколько параметров в asynctask (или что-то еще), используйте специальный класс, который содержит все ваши параметры сразу. Использование пакета - прекрасное решение проблемы, которой у вас не должно быть. Нет закона против создания специального класса, который будет содержать именно то, что вам нужно, и ничего больше.
Кроме того, почему вы не используете сопрограммы? Asynctasks являются так 2014.
источник
Это решается путем создания подклассов. У 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"); } }
источник