1

Я искал все сообщения, которые я могу найти, и никто, кажется, не помогает в моей ситуации. У меня есть проект андроида, который использует веб-службы, чтобы вывести почасовые метеорологические данные и заполнить listView результатами.Пользовательский адаптер для Android и asyncTask не обновляется listView

Странная проблема, с которой я столкнулся, заключается в том, что когда я отлаживаю проект на своем телефоне Android, основное действие пустое, а listView не заполняется. Если я запустил проект из студии Android и заблокировал свой телефон, а затем откройте мой телефон, приложение откроется на моем телефоне со всем списком, соответствующим образом отформатированным и заполненным.

Я чувствую, что проблема с состоянием гонки между асинхронностью и адаптером, но я не могу ее решить. Я попытался сделать мой asyncTask внутренним частным классом и вызвать notifyDataSetChanged на адаптере внутри метода onPostExecute, но безрезультатно. Я чувствую, что это должно быть что-то простое, но я относительно новичок в Android dev, поэтому я застрял.

У меня есть три класса, которые я выложу уместный код из

MainActivity.java (onCreate)

public class MainActivity extends ActionBarActivity { 

    ArrayList<Weather> w = new ArrayList<Weather>(); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     DownloadWeatherTask myTask = new DownloadWeatherTask(w); 
     WeatherAdapter myAdapter = new WeatherAdapter(this,w); 


     ListView l = (ListView) findViewById(R.id.weatherList); 
     l.setAdapter(myAdapter); 

     myTask.execute(); 
    } 
} 

WeatherAdapter.java

public class WeatherAdapter extends ArrayAdapter<Weather>{ 

    public WeatherAdapter(Context context, ArrayList<Weather> weather) { 
     super(context, R.layout.item_weather, weather); 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 
     // Get the data item for this position 
     Weather forecast = getItem(position); 
     // Check if an existing view is being reused, otherwise inflate the view 
     if (convertView == null) { 
      convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_weather, parent, false); 
     } 
     // Lookup view for data population 
     TextView tvTime = (TextView) convertView.findViewById(R.id.listTime); 
     TextView tvDescr = (TextView) convertView.findViewById(R.id.listDescr); 
     TextView tvTemp = (TextView) convertView.findViewById(R.id.listTemp); 
     TextView tvHumid = (TextView) convertView.findViewById(R.id.listHumid); 
     ImageView ivWeather = (ImageView)  convertView.findViewById(R.id.weatherImg); 
     // Populate the data into the template view using the data object 
     tvTime.setText(forecast.time); 
     tvDescr.setText(forecast.description); 
     tvTemp.setText(forecast.temperature+"°(F)"); 
     tvHumid.setText(forecast.humidity+"% humidity"); 
     ivWeather.setImageBitmap(forecast.weatherImg); 
     // Return the completed view to render on screen 
     return convertView; 
    } 

} 

DownloadWeatherTask.java

public class DownloadWeatherTask extends AsyncTask<Void,Void,Void>{ 

    ArrayList<Weather> data; 

    public DownloadWeatherTask(ArrayList<Weather> a){ 
     data = a; 
    } 

    public ArrayList<Weather> getData() { 
     return data; 
    } 


    protected Void doInBackground(Void...params) { 
     try { 
      String website =  "http://api.wunderground.com/api/1111111111111/geolookup/q/autoip.json"; 
      URL site = new URL(website); 
      HttpURLConnection weatherUnderground = (HttpURLConnection)  site.openConnection(); 
      weatherUnderground.connect(); 

      JsonParser weatherParser = new com.google.gson.JsonParser(); 

      JsonElement weatherJson = weatherParser.parse(new InputStreamReader((InputStream) weatherUnderground.getContent())); 

      JsonObject weatherObj = weatherJson.getAsJsonObject(); 

      String zip = weatherObj.get("location").getAsJsonObject().get("zip").getAsString(); 
      String city = weatherObj.get("location").getAsJsonObject().get("city").getAsString(); 
      String state = weatherObj.get("location").getAsJsonObject().get("state").getAsString(); 

      String hourly = "http://api.wunderground.com/api/111111111111/hourly/q/" + state + "/" + city + ".json"; 
      URL hourlySite = new URL(hourly); 
      HttpURLConnection hourlyConnection = (HttpURLConnection) hourlySite.openConnection(); 
      hourlyConnection.connect(); 

      com.google.gson.JsonParser hourlyParser = new com.google.gson.JsonParser(); 

      JsonElement hourlyWeatherJson = weatherParser.parse(new InputStreamReader((InputStream) hourlyConnection.getContent())); 

      JsonArray weatherArr = hourlyWeatherJson.getAsJsonObject().get("hourly_forecast").getAsJsonArray(); 
      int l = weatherArr.size(); 

      for (int i = 0; i < l; i++) { 
       String date = weatherArr.get(i).getAsJsonObject().get("FCTTIME").getAsJsonObject().get("pretty").getAsString(); 
       String temp = weatherArr.get(i).getAsJsonObject().get("temp").getAsJsonObject().get("english").getAsString(); 
       String condition = weatherArr.get(i).getAsJsonObject().get("condition").getAsString(); 
       String humidity = weatherArr.get(i).getAsJsonObject().get("humidity").getAsString(); 
       String iconUrl = weatherArr.get(i).getAsJsonObject().get("icon_url").getAsString(); 
       Bitmap icon = getBitmapFromURL(iconUrl); 
       data.add(new Weather(date, condition, temp, humidity, icon)); 
      } 
     } catch (IOException e) { 
      Log.e("Error: ",e.toString()); 
     } 

     return null; 

    } 


    protected void onPostExecute(Void...params){ 

    } 
} 

Ниже приведены ссылки на мои скриншоты, показывающие, что приложение не заполняет listView, и приложение работает правильно, когда программа запускается, когда телефон изначально заблокирован.

http://i57.tinypic.com/i55b0n.png http://i62.tinypic.com/rho477.png

Любая помощь будет высоко оценена !!

Благодаря

ответ

1

В postExecute(), вам необходимо обновить список адаптера, а затем вызвать его notifyDataSetChanged метод. Я подозреваю, что вы забыли обновить данные адаптера.

Другой вариант - создать новый адаптер с новыми данными и установить новый адаптер в ListView.

+0

Я не уверен, как получить доступ к адаптеру из asyncTask. Я попытался сделать класс Async подклассом и сделать это таким образом, а также передать его как параметр для моего класса async, но не работал. – BretD

+1

Я передал бы его конструктору AsyncTask – GreyBeardedGeek

1

Я понял, в чем проблема! Я не добавил @Override в свой метод onPostExecute(), поэтому он никогда не вызывался.

Я добавил notifyDataSetChanged в мой onPostExecute, как было предложено, и работал, как только я добавил @override к моему методу.

Смежные вопросы