【问题标题】:AsyncTask doInBackground to return multiple stringsAsyncTask doInBackground 返回多个字符串
【发布时间】:2016-12-19 21:10:18
【问题描述】:

我正在尝试在 android studio 中构建一个非常基本的天气应用程序。我正在使用 AsyncClass 返回多个字符串。

正如您在代码中看到的,我使用了一个名为“Wrapper”的类来存储我的字符串,因此我可以只返回一个类对象并在 AsyncTask 的 onPostExecute 方法中使用它。我面临的问题是,当我测试应用程序时,所有返回的字符串都以某种方式未定义(Wrapper 类的默认值)。这意味着字符串没有在 doInBackground 方法中更新,我似乎无法弄清楚为什么!

My Activity

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.i(MainActivity.class.getSimpleName(), "Can't connect to Google Play Services!");
    }
    private class Wrapper
    {
          String Temperature = "UNDEFINED";
         String city = "UNDEFINED";
         String country = "UNDEFINED";
    }

    private class GetWeatherTask extends AsyncTask<String, Void, Wrapper> {
        private TextView textView;

        public GetWeatherTask(TextView textView) {
            this.textView = textView;
        }

        @Override
        protected Wrapper doInBackground(String... strings) {
            Wrapper w = new Wrapper();
            String Temperature = "x";
            String city = "y";
            String country = "z";

            try {
                URL url = new URL(strings[0]);
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

                InputStream stream = new BufferedInputStream(urlConnection.getInputStream());
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream));
                StringBuilder builder = new StringBuilder();

                String inputString;
                while ((inputString = bufferedReader.readLine()) != null) {
                    builder.append(inputString);
                }

                JSONObject topLevel = new JSONObject(builder.toString());
                JSONObject main = topLevel.getJSONObject("main");
                JSONObject cityobj = topLevel.getJSONObject("city");
                Temperature = String.valueOf(main.getDouble("temp"));
                city = cityobj.getString("name");
               country = cityobj.getString("country");

                w.Temperature= Temperature;
                w.city= city;
                w.country=country;

                urlConnection.disconnect();
            } catch (IOException | JSONException e) {
                e.printStackTrace();
            }
            return w;
        }

        @Override
        protected void onPostExecute(Wrapper w) {
            textView.setText("Current Temperature: " + w.Temperature + " C" + (char) 0x00B0
                       +"\n" + "Current Location: "+ w.country +"\n" + "City: "+  w.city );
        }
    }
}

更新:

原来我在代码中使用了错误的 url,我使用的是: http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&units=%s&appid=%s

我应该一直在使用:

http://api.openweathermap.org/data/2.5/forecast?lat=%f&lon=%f&units=%s&appid=%s

-我应该使用天气预报而不是天气

【问题讨论】:

  • 抱歉,现在编辑
  • 在捕获块中输入return null;。在onPostExecute() 使用之前检查w==null 是否。
  • 现在会这样做并更新您
  • 做了一个简单的 if else
  • 您应该首先检查您从服务器返回的内容。如果它是有效的 json。所以检查builder.toString()的值。

标签: java android android-asynctask


【解决方案1】:

你的错误从这里开始

JSONObject main = topLevel.getJSONObject("main");

可能是因为topLevel 对象没有"main" 键。

{  
   "city":{  },
   "cod":"200",
   "message":0.1859,
   "cnt":40,
   "list":[  ]
}

将您的 JSON 放入此处。 https://jsonformatter.curiousconcept.com/

您会注意到"list" 元素中有很多很多"main" 键,但您必须解析从getJSONArray("list") 开始的那些。


基本上是这样的

String city = "undefined";
String country = "undefined";
List<Double> temperatures = new ArrayList<Double>();

try {
    JSONObject object = new JSONObject(builder.toString());
    JSONObject jCity = object.getJSONObject("city");
    city = jCity.getString("name");
    country = jCity.getString("country");

    JSONArray weatherList = object.getJSONArray("list");
    for (int i = 0; i < weatherList.length(); i++) {
        JSONObject listObject = weatherList.getJSONObject(i);
        double temp = listObject.getJSONObject("main").getDouble("temp");
        temperatures.add(temp);
    }

} catch (JSONException e) {
    e.printStackTrace();
}

return new Wrapper(city, country, temperatures);

【讨论】:

  • 当我编辑如何解析 json 时似乎没有工作
  • 我使用适合我的代码进行了编辑。您只需编辑代码以匹配它(主要更改 Wrapper 类以获取列表)
  • 将尝试此操作并回复您
  • 我收到一个异常,说列表 12-19 22:28:24.164 26414-26458/com.deshpande.locationdemo W/System.err: org.json.JSONException: No value当我使用你的代码时的列表
  • 我确信它对我有用。我复制了您提供的确切链接。和Log.d("temps", String.valueOf(temperatures)); 之前返回显示我D/temps: [286.59, 286.9, 288.09, 288.37,...]。所以我认为你的问题是 StringBuilder 没有得到所有的数据。
【解决方案2】:

在研究了您的代码之后,您的 try 块失败,即返回您的对象但为空,或者您的 JSON 解析有问题。如果您可以向我们展示您尝试解析的 JSON,那将是一个很大的帮助。

话虽如此,它仍然显示为“未定义”的事实是因为这是您初始化它的方式,并且因为(JSON 解析可能失败),该对象正在以未编辑状态返回。

编辑:

您解析 JSON 错误。您试图在顶层目录中找到一个名为“main”的对象,但主要对象仅存在于名为 list 的数组中!

请在此处查看更易于查看和直观的表示:http://prntscr.com/dlhlrk

您可以使用此站点来帮助可视化您的 JSON 并基于它创建适当的解决方案。 https://jsonformatter.curiousconcept.com/

【讨论】:

  • 这是一个答案吗?您最好在 cmets 中发布此类评论。
  • 是的,这确实回答了为什么会显示“未定义”的问题,不,我不能发表评论,因为某些令我困惑的原因,我不能离开 cmets,直到我的声誉达到50.
  • 你来得太晚了。 UNDEFINED 问题早就被添加的return null; 解决了。
  • 编辑了我的答案@HummingDev
【解决方案3】:

查看您之前发布的 API (api.openweathermap.org),您正在尝试访问不存在的变量。我建议你看看 API returns 是什么,如果你得到一个 JSONException,试着一一获取变量

编辑: 您使用的是什么 API?在您最初的帖子中,您说它是http://api.openweathermap.org/data/2.5/weather,但在上面的评论中您说它是http://api.openweathermap.org/data/2.5/forecast。

如果您使用的是天气 API(如最初所述),则可以使用以下内容:

    @Override
    protected Wrapper doInBackground(String... strings) {
        Wrapper w = new Wrapper();

        try {
            URL url = new URL(strings[0]);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

            InputStream stream = new BufferedInputStream(urlConnection.getInputStream());
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream));
            StringBuilder builder = new StringBuilder();

            String inputString;
            while ((inputString = bufferedReader.readLine()) != null) {
                builder.append(inputString);
            }

            Log.d("JSON", builder.toString());

            JSONObject topLevel = new JSONObject(builder.toString());
            JSONObject main = topLevel.getJSONObject("main");
            JSONObject sys = topLevel.getJSONObject("sys");

            w.Temperature = String.valueOf(main.getDouble("temp"));
            w.city = topLevel.getString("name");
            w.country = sys.getString("country");

            urlConnection.disconnect();
        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }
        return w;
    }

【讨论】:

  • 奇怪我不认为我解析 json 错误现在会仔细检查
  • 谢谢伙计,已经知道有四个项目同时打开,这让我不知道哪个链接是哪个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-30
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 2014-01-17
  • 1970-01-01
相关资源
最近更新 更多