如何在 android 中通过 AsyncTask return 多个列表 <String>?

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

我创建了一个 AsynTaskInsideActivity class,它在 MainActivity 中扩展 AsyncTask<Void, Void, List<String>> 作为内部 class。我正在使用此 AsynTaskInsideActivitylocation table 获取所有记录。此位置 table 具有以下列:

我想从每个单独的列中获取记录。因此,为了存储每个单独列的每条记录,我创建了四个 List 类型的数组(即每个列一个)并成功地将检索到的 Cursor 数据存储在每个数组中。现在,问题是我需要 return 每一列的记录。因此,具体来说,我如何 return 来自一个 AsyncTask class 的那四个单独的 List 类型数组。目前,我只 returning 列表类型数组,即 locationId,它具有我从位置 table 的 location_id 列中获取的所有位置 ID。

问题:

这是我的 AsyncTask class 的样子:

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

}

您可以 return 从 AsyncTask<Void, Void, List<List<String>> 扩展您的 AsyncTask 并完成它,但这不是最好的方法。

更好的方法是扩展 AsyncTask<Void, Void, List<Location>>,其中 Location 定义为:

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
}

你的循环看起来像这样:

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;

好吧,在通过互联网研究这个问题的解决方案并投入几个小时将单个 AsyncTask 设置为 return 多个值之后,我想出了一个嵌套 List 数组的解决方案即 List<List<String>>

原创作品:

@Simon:谁给了我一个指示(或暗示)我如何更新我的 AsyncTask 以获得完成的工作,事实证明这真的很有帮助。
@VERT9x:感谢您付出努力并用不同的方法完成工作。

解法:

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

我所做的更改:

  • 将 AsyncTask class 和 doInBackground() return 类型的第 3 个参数更改为 List<List<String>>,因此它可以 return 多个值。
  • 解决办法见下面这两行:

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