How can I return an ArrayList from my AsyncTask?

I have an AsynkTask method in my MainActivity that looks like this:

class chargeCars extends AsyncTask<Void, Integer, ArrayList<Car>> { protected void onPreExecute(){ } protected ArrayList<Car> doInBackground(Void... params) { ArrayList<Car> cars = new ArrayList<Car>(); cars.add(new Car(1,"Car1"); cars.add(new Car(2,"Car2"); cars.add(new Car(3,"Car3"); return cars; } protected void onProgressUpdate(){ } protected void onPostExecute(ArrayList<Car> c){ } } 

where Car is the object that I declared in another Class , and which its constructor is:

 public Car(int idCar, String name) { this.idCar = idCar; this.name = name; } 

and I know that return cars; returns an ArrayList named cars in the onPostExecute method, but I tried to extract this ArrayList from it, and I could not, because it always told me that onPostExecute should be Void .

I have another ArrayList declared in my MainActivity class:

 ArrayList<Car> totalCars = new ArrayList<Car>(); 

so I tried to clone cars ArrayList into my totalCars ArrayList in my onPostExecute method, but it gives me an error saying that:

'clone ()' is protected by access in 'java.lang.Object'

Here is the code that is trying to clone my ArrayList:

 protected void onPostExecute(ArrayList<Car> c) { for(Car cr: c) { totalCars.add(cr.clone()); } } 

Therefore, I also tried adding my values โ€‹โ€‹directly to my totalCars ArrayList using my doInBackground method:

 totalCars.add(new Car(1,"Car1"); totalCars.add(new Car(2,"Car2"); totalCars.add(new Car(3,"Car3"); 

but when I execute the AsyncTask method:

 new chargeCars().execute(); 

the size of my totalCars ArrayList is 0.

What should I do? I am completely blocked and I searched in SO for an answer, but I could not find anything that helped me.

EDIT: My Car Class:

 public class Car { private int idCar; private String name; public Car(){}; public Car(int idCar, String name) { this.idCar = idCar; this.name = name; } public void setIdCar(int idCar) { this.idCar = idCar; } public int getIdCar() { return idCar; } public void setName(String name) { this.name = name; } public String getName() { return name; } } 

EDIT 2: I posted some magazines to find out what exactly my program does, and I got strange results:

As Clairvoyant said, I use both of his methods, but either of them works. What could I see? Well, I saw that in the onPostExecute method onPostExecute ArrayList contains values โ€‹โ€‹in both methods. There is no problem.

The problem is that when I execute AsyncTask in the onCreate method of my onCreate class MainActivity my ArrayList totalCars does not matter inside, but in the onPostExecute method of my AsyncTask it has all the values โ€‹โ€‹that I entered in the ArrayList.

What could be the problem?

EDIT 3: I also tried:

 public class MainActivity extends ActionBarActivity { ArrayList<Car> cars = new ArrayList<Car>(); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new chargeCars().execute(); Log.d("Size onCreate: ", "" + cars.size()); //It returns me a 0 -->Incorrect } class chargeCars extends AsyncTask<Void, Integer, Boolean> { protected void onPreExecute(){ } protected ArrayList<Car> doInBackground(Void... params) { cars.add(new Car(1,"Car1"); cars.add(new Car(2,"Car2"); cars.add(new Car(3,"Car3"); Log.d("Size: ", "" + cars.size()); //It gives me the size equals to 3 -->Correct return true; } protected void onProgressUpdate(){ } protected void onPostExecute(boolean c){ } } } 

But still does not work. I also tried to make ProgressDialog safe that my AsyncTask ended when I try to use my Log in my onCreate method, but it also gives me an error (I have another question in SO about this, but I don't know if this is good practice in SO to directly refer to another question, so I do not post it here).

Am I doing something wrong? Why in my doInBackground it give me the correct size the ArrayList method and not in my onCreate method?

Thanks in advance!

+5
source share
2 answers

Am I doing something wrong? Why in my doInBackground does this give me the correct ArrayList size and not my onCreate method?

Since the execution is asynchronous and the UI Thread does not complete the execution of your AsyncTask in order to continue its execution. To return results when your AsyncTask completes without blocking the UI Thread , you can use a delegate / lister.

Let me declare an interface at the top of your action and let it implement that interface (you will need to implement the methods). When onCarsCompleted is onCarsCompleted , you can print the correct size of your ArrayList

  public class MainActivity extends ActionBarActivity implements OnCarsListener { public interface OnCarsListener { void onCarsCompleted(ArrayList<Car> cars); void onCarsError(String error); } // the other code public void onCarsCompleted(ArrayList<Car> cars) { Log.d("Size: ", "" + cars.size()); } public void onCarsError(String error) { } } 

Now we add a constructor to your AsyncTask , which takes an object of type OnCarsListener as a parameter, and we save the reference to the object in the chargeCars , and onPostExecute exchange the results of your calculations back to Activity :

 class chargeCars extends AsyncTask<Void, Integer, ArrayList<Car>> { private final OnCarsListener mListener; ArrayList<Car> cars = new ArrayList<Car>(); public chargeCars(OnCarsListener listener) { mListener = listener; } protected void onPreExecute(){ } protected ArrayList<Car> doInBackground(Void... params) { cars.add(new Car(1,"Car1"); cars.add(new Car(2,"Car2"); cars.add(new Car(3,"Car3"); Log.d("Size: ", "" + cars.size()); //It gives me the size equals to 3 -->Correct return cars; } protected void onProgressUpdate(){ } protected void onPostExecute(ArrayList<Car> cars){ if (mListener != null) { mListener.onCarsCompleted(cars); } } } 

And of course, you need to create an AsyncTask instance, for example

new chargeCars(this).execute();

+6
source

Method 1: Do not use the clone just to use the object:

 protected void onPostExecute(ArrayList<Car> c) { super.onPostExecute(); for(Car cr: c) { totalCars.add(cr); } //Code for further execution } 

Method 2: Run the method that will be called onPostExceute () after it receives an ArrayList

  protected void onPostExecute(ArrayList<Car> c) { super.onPostExecute(); setValues(c); } private void setValues(ArrayList<Car> c){ for(Car cr: c) { totalCars.add(cr); } //Code for further execution } 
+2
source

All Articles