简体   繁体   中英

How to return multiple List<String> via AsyncTask in android?

I have created an AsynTaskInsideActivity class that extends AsyncTask<Void, Void, List<String>> within the MainActivity as an inner class. I am using this AsynTaskInsideActivity for getting all the records from the location table. This location table has following columns:

  • location_id
  • country
  • state
  • zip_code

And I want to fetch records from each individual column. So, for storing every record of each individual column I created four List type arrays (ie one for each column) and successfully stored the retrieved Cursor data within each of them. Now, the problem is I need to return every column's records. So, to be specific how can I return those four individual List type arrays from a one AsyncTask class. Currently, I am returning only the list type array namely locationId which has all the location ids I fetched from location table's location_id column.

Questions:

  • How can I return multiple list array items from a single AsyncTask class? After all when we query a database, sometimes we need records from multiple columns from an individual table to process further operations.
  • Is there any better approach that I can use to overcome this problem? or I have to believe some things are really impossible.

This is what my AsyncTask class looks like:

public class AsyncTaskInsideActivity extends AsyncTask<Void, Void, List<String>> {

private static final String CLASS_TAG = AsyncTaskInsideActivity.class.getSimpleName();

@Override
protected List<String> doInBackground(Void... params) {

    Log.v(CLASS_TAG, "AsyncTaskInsideActivity started successfully....");

    SoCalledDbHelper soCalledDbHelper = new SoCalledDbHelper
            (getBaseContext());

    //key-value pairs for inserting data into the table
    ContentValues soCalledValues = new ContentValues();
    soCalledValues.put(SoCalledContract.LocationTable.COLUMN_CITY_NAME, "Kim Kardishian");
    soCalledValues.put(SoCalledContract.LocationTable.COLUMN_STATE, "No Ass Holes");
    soCalledValues.put(SoCalledContract.LocationTable.COLUMN_ZIP_CODE, 007);

    //insert location data
    soCalledDbHelper.addLocationData(soCalledValues);
    //For storing the cursor data which will be retrieved by the read query.
    Cursor locationDataCursor;

    //Query for all the data in the location table
    locationDataCursor = soCalledDbHelper.getAllLocationData(null, null, null, null);

    List<String> sCLocationId = new ArrayList<String>();
    List<String> sCCityName = new ArrayList<String>();
    List<String> sCState = new ArrayList<String>();
    List<String> sCZipCode = new ArrayList<String>();

    if (locationDataCursor.getCount() > 0) {
        //Reset the cursor location
        locationDataCursor.moveToPosition(-1);
        while (locationDataCursor.moveToNext()) {
            //Extracting data from the location cursor
            sCLocationId.add(locationDataCursor.getString
                    (locationDataCursor.getColumnIndex("_id")));
            sCCityName.add(locationDataCursor.getString
                    (locationDataCursor.getColumnIndex("city_name")));
            sCState.add(locationDataCursor.getString
                    (locationDataCursor.getColumnIndex("state")));
            sCZipCode.add(locationDataCursor.getString
                    (locationDataCursor.getColumnIndex("zip_code")));
        }
        Log.i(CLASS_TAG, "Success: Cursor has data! #Total Records: " +
                locationDataCursor.getCount());
        for (String locationIds : sCLocationId) {
            Log.i(CLASS_TAG, "Location Id: + " + locationIds);
        }
        for (String cityNamez : sCCityName) {
            Log.i(CLASS_TAG, "City Names: + " + cityNamez);
        }
        for (String statesNames : sCState) {
            Log.i(CLASS_TAG, "State Names: + " + statesNames);
        }
        for (String zipCodes : sCZipCode) {
            Log.i(CLASS_TAG, "Zip Codes: + " + zipCodes);
        }
    } else {
        Log.w(CLASS_TAG, "Error: Cursor is empty! #Total Records: " +
                locationDataCursor.getCount());
    }
    locationDataCursor.close();
    soCalledDbHelper.close();
    Log.v(CLASS_TAG, "AsyncTaskDbHelper ended successfully....");
    return sCLocationId;
}

}

You could just return extend your AsyncTask off of AsyncTask<Void, Void, List<List<String>> and be done with it but this is not the best approach.

A better approach would be to extend off of AsyncTask<Void, Void, List<Location>> where Location is defined as:

public class Location
{
    private String location_id;
    private String country;
    private String state;
    private String zip_code;

    // Constructors, getters and setters go here. Your IDE should be able to generate them.
    // You can also override the toString method to format the output better
}

Your loop would then look something like this:

List<Location> locations_list = new ArrayList<Location>();
if (locationDataCursor.moveToFirst()) {// Moves to first if cursor is not empty
    do{
        Location location = new Location();
        //Extracting data from the location cursor
        location.setID(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("_id")));
        location.setCity(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("city_name")));
        location.setState(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("state")));
        location.setZip(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("zip_code")));

        // Add location to the list
        locations_list.add(location)
    }while (locationDataCursor.moveToNext())

    Log.i(CLASS_TAG, "Success: Cursor has data! #Total Records: " +
            locationDataCursor.getCount());
    for (Location l : locations_list) {
        Log.i(CLASS_TAG, "Location: " + l.toString());
    }
} else {
    Log.w(CLASS_TAG, "Error: Cursor is empty!"
}

// Close any open DB objects
locationDataCursor.close();
soCalledDbHelper.close();
Log.v(CLASS_TAG, "AsyncTaskDbHelper ended successfully....");

// Return the list of locations
return locations_list;

Well, after researching for the solution to this question over the internet and devoting several hours for getting the single AsyncTask to return multiple values I came up with a solution with a nested List array ie List<List<String>>

Original Credits:

@ Simon : Who gave me an indication (or hint) that how could I update my AsyncTask to get the job done, that was proved to be really helpful.
@ VERT9x : Thanks for putting the effort and getting the job done with a different approach.

Solution:

public class AsyncTaskInsideActivity extends AsyncTask<Void, Void, List<List<String>>> {

    private static final String CLASS_TAG = AsyncTaskInsideActivity.class.getSimpleName();

    @Override
    protected List<String> doInBackground(Void... params) {

Log.v(CLASS_TAG, "AsyncTaskInsideActivity started successfully....");

SoCalledDbHelper soCalledDbHelper = new SoCalledDbHelper
        (getBaseContext());

//key-value pairs for inserting data into the table
ContentValues soCalledValues = new ContentValues();
soCalledValues.put(SoCalledContract.LocationTable.COLUMN_CITY_NAME, "Kim Kardishian");
soCalledValues.put(SoCalledContract.LocationTable.COLUMN_STATE, "No Ass Holes");
soCalledValues.put(SoCalledContract.LocationTable.COLUMN_ZIP_CODE, 007);

//insert location data
soCalledDbHelper.addLocationData(soCalledValues);
//For storing the cursor data which will be retrieved by the read query.
Cursor locationDataCursor;

//Query for all the data in the location table
locationDataCursor = soCalledDbHelper.getAllLocationData(null, null, null, null);

List<String> sCLocationId = new ArrayList<String>();
List<String> sCCityName = new ArrayList<String>();
List<String> sCState = new ArrayList<String>();
List<String> sCZipCode = new ArrayList<String>();

if (locationDataCursor.getCount() > 0) {
    //Reset the cursor location
    locationDataCursor.moveToPosition(-1);
    while (locationDataCursor.moveToNext()) {
        //Extracting data from the location cursor
        sCLocationId.add(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("_id")));
        sCCityName.add(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("city_name")));
        sCState.add(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("state")));
        sCZipCode.add(locationDataCursor.getString
                (locationDataCursor.getColumnIndex("zip_code")));
    }
    Log.i(CLASS_TAG, "Success: Cursor has data! #Total Records: " +
            locationDataCursor.getCount());
    for (String locationIds : sCLocationId) {
        Log.i(CLASS_TAG, "Location Id: + " + locationIds);
    }
    for (String cityNamez : sCCityName) {
        Log.i(CLASS_TAG, "City Names: + " + cityNamez);
    }
    for (String statesNames : sCState) {
        Log.i(CLASS_TAG, "State Names: + " + statesNames);
    }
    for (String zipCodes : sCZipCode) {
        Log.i(CLASS_TAG, "Zip Codes: + " + zipCodes);
    }
} else {
    Log.w(CLASS_TAG, "Error: Cursor is empty! #Total Records: " +
            locationDataCursor.getCount());
}
locationDataCursor.close();
soCalledDbHelper.close();

//Creating a List that can store List(s) within it.
//List of Lists String
List<List<String>> arrayOfLists = new ArrayList<List<String>>();

//Adding those Lists that was used to store each column records
arrayOfLists.add(sCLocationId);
arrayOfLists.add(sCCityName);
arrayOfLists.add(sCState);
arrayOfLists.add(sCZipCode);

//Start iterating over the parent arrayOfLists List 
for(int i = 0; i < arrayOfLists.size(); i++) {
    //Print each arrayOfLists data item it contains
    Log.v(CLASS_TAG, "Parent List: " + arrayOfLists.get(i).toString());
    //Start iterating over child of arrayOfLists List
    for(int j = 0; j < arrayOfLists.get(i).size(); j++) {
        //Print each arrayOfLists CHILD data item it contains
        Log.v(CLASS_TAG, "Child List: " + arrayOfLists.get(i).get(j).toString());
    }
}
        //Size of the arrayOfLists  
        Log.v(CLASS_TAG, "Parent List Size: " + Integer.toString(arrayOfLists.size()));
        //Size of the arrayOfLists child container  
        Log.v(CLASS_TAG, "Child List Size: " + Integer.toString(arrayOfLists.get(1).size()));
Log.v(CLASS_TAG, "AsyncTaskDbHelper ended successfully....");
return arrayOfLists;
}

Changes I Made:

  • Changed the 3rd parameter of AsyncTask class and doInBackground() return type to List<List<String>> , so it can return multiple values.
  • For solution see under these two lines:

    locationDataCursor.close();
    soCalledHelper.close();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM