Glave Glave - 27 days ago 18
Android Question

Returning a List correctly

How do I return a List correctly?

I am programming an App with OSMdroid and I want to use the variables "longitude" and "latitude" of the class "Place"(on the bottom of this Post) to ultimately use them in the "onPostExecute" method, right where I set the "PLACEHOLDERS".

Android Studio wants me to alter the line "return loadXmlFromNetwork(urls[0]);", which executes the code below, but I dont know how exactly (The methods below are in the same class).

private class DownloadXmlTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
try {
//Here I want to recieve the list
return loadXmlFromNetwork(urls[0]);
} catch (IOException e) {
return getResources().getString(R.string.connection_error);
} catch (XmlPullParserException e) {
return getResources().getString(R.string.xml_error);
}

}

@Override
protected void onPostExecute(List<Place> result) {

MapView map = (MapView) findViewById(R.id.map);
IMapController mapController = map.getController();
mapController.setZoom(17);
//Here I want to use the latitude and longitude variables of the List
GeoPoint myLocation = new GeoPoint(PLACEHOLDER(latitude), PLACEHOLDER(longitude));
mapController.animateTo(myLocation);

}
}


This is where I recieve the list for the first time:

private List<Place> loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
InputStream stream = null; // Instantiate the parser
XMLParser XMLParser = new XMLParser();
List<Place> places = null;

try {
stream = downloadUrl(urlString);
places = XMLParser.parse(stream); // Makes sure that the InputStream is closed after the app is finished using it.
} finally {
if (stream != null) {
stream.close();
}
}

return places;
}


This is my Place class:

public class Place {
private String longitude;
private String latitude;
private String place_id;

public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}

public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}

public String getPlace_id() {
return place_id;
}
public void setPlace_id(String place_id) {this.place_id = place_id;}

@Override
public String toString() {
return "ID: " + place_id + "\n" + "Longitude: " + longitude + "\n" + "Latitude: " + latitude;
}

Nit Nit
Answer

The three parametric types of the AsyncTask are AsyncTask<Params, Progress, Result>

(See the AsyncTask documentation)

If you want to have a List<Place> as a result, you must replace

private class DownloadXmlTask extends AsyncTask<String, Void, String> {

with

private class DownloadXmlTask extends AsyncTask<String, Void, List<Place>> {

Your doInBackground() method must then return a List<Place> instead of a String. The line where you call loadXmlFromNetwork(urls[0]) will then work since loadXmlFromNetwork() do returns a List<Place>, but the two other return lines in your catches clauses won't compile anymore since they return String. You must change them, and return null, for example.

Edit: As @Code-Apprentice said, the exception shouldn't just be ignored. You could use boolean flags in order to check them later.

private class DownloadXmlTask extends AsyncTask<String, Void, List<Place>> {
    private boolean mConnectionError;
    private boolean mXMLError;

    @Override
    protected List<Place> doInBackground(String... urls) {
        try {
            //Here I want to recieve the list
            return loadXmlFromNetwork(urls[0]);       
        } catch (IOException e) {
            mConnectionError = true;
            return null;
        } catch (XmlPullParserException e) {
            mXMLError = true;
            return null;
        }

    }

    @Override
    protected void onPostExecute(List<Place> result) {

        if (result != null) {
            MapView map = (MapView) findViewById(R.id.map);
            IMapController mapController = map.getController();
            mapController.setZoom(17);
            //Here I want to use the latitude and longitude variables of the List
            GeoPoint myLocation = new GeoPoint(PLACEHOLDER(latitude), PLACEHOLDER(longitude)); 
            mapController.animateTo(myLocation);

        } else {
            // An error happened, check mConnectionError and
            // mXMLError in order to display an error message.

        }
    }
}
Comments