【问题标题】:Returning a List correctly正确返回列表
【发布时间】:2016-11-07 14:02:10
【问题描述】:

如何正确返回列表?

我正在使用 OSMdroid 编写一个应用程序,我想使用“Place”类的变量“经度”和“纬度”(在这篇文章的底部)最终在“onPostExecute”方法中使用它们,对吧我在其中设置了“PLACEHOLDERS”。

Android Studio 想让我修改“return loadXmlFromNetwork(urls[0]);”这行代码,它会执行下面的代码,但我不知道具体如何(下面的方法在同一个类中)。

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

    }
}

这是我第一次收到名单的地方:

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

这是我的 Place 课程:

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

【问题讨论】:

    标签: android xml list oop


    【解决方案1】:

    AsyncTask 的三种参数类型是AsyncTask&lt;Params, Progress, Result&gt;

    (见AsyncTask documentation

    如果你想要一个List&lt;Place&gt;作为结果,你必须替换

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

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

    您的doInBackground() 方法必须返回List&lt;Place&gt; 而不是String。然后,您调用 loadXmlFromNetwork(urls[0]) 的行将工作,因为 loadXmlFromNetwork() 确实返回 List&lt;Place&gt;,但您的 catches 子句中的另外两个返回行将不再编译,因为它们返回 String。例如,您必须更改它们并返回 null

    编辑: 正如@Code-Apprentice 所说,不应忽略异常。您可以使用布尔标志以便稍后检查它们。

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

    【讨论】:

    • 这个答案可以更完整,还包括显示错误消息的建议,而不是仅仅忽略异常。
    • @Code-Apprentice 现在错误似乎消失了,但我正在努力从我的 PLACEHOLDERS 所在的列表中获取价值。我以为我可以用“结果(纬度)”得到它们,但这似乎不起作用。 Nit:我也不明白你对 catches 条款的评论。请您进一步解释一下吗?
    • @Glave 您应该可以使用result.get(n).getLatitude() 访问这些值,请务必检查result != nulln &lt; result.size()
    • 终于成功了。太感谢了。你不知道这对我的未来有多重要!
    • 不客气@Glave。关于 catches 子句,我是说你不能返回 String 值(getResources().getString(R.string.connection_error)String 类型),因为 doInBackground() 方法应该返回 List&lt;Place&gt;,这就是我建议的原因而是返回null,并以另一种方式管理错误消息。
    【解决方案2】:

    最简单的解决方法是改变

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

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

    AsyncTask 的最后一个参数是结果类型。您将需要一种不同的方式来传达错误情况。例如,您可以添加一些布尔字段以用作标志和适当的 gettter 来访问它们。此外,AsyncTask 不应对 UI 中显示的错误消息负责。这违反了单一职责原则。

    【讨论】:

    • 我也认为 XMLParser 会抛出,所以他不仅需要 finnaly,还需要 catch
    • @X3Btel 异常在 throws 子句中声明并向上传播调用堆栈。然后他们被困在 doInBackground() 中。
    • 我将 Nits 的答案标记为正确,但由于它或多或少是相同的答案,而且非常罕见,我实际上得到了我的问题的任何答案,无论如何我还是要感谢你该死的。
    • @Glave 没问题。他的回答要详细得多。当您有足够的代表时,您可以对我们的两个答案进行投票以表示您的赞赏。
    猜你喜欢
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-06-19
    • 2020-01-09
    相关资源
    最近更新 更多