简体   繁体   English

Android自定义适配器和asyncTask不更新listView

[英]Android custom adapter and asyncTask not updating listView

I've searched all the posts I can find, and none seem to help with my situation. 我搜索了所有可以找到的帖子,但似乎没有一个对我的情况有所帮助。 I have an android project that uses web services to pull down hourly weather data and populate a listView with the results. 我有一个使用网络服务来提取每小时天气数据并用结果填充listView的android项目。

The weird problem I'm having is that when I debug the project on my android phone, the main activity is blank and the listView isn't populated. 我遇到的怪异问题是,当我在Android手机上调试项目时,主要活动为空白,并且未填充listView。 If I run the project from android studio with my phone locked, and then unlock my phone the app opens on my phone with all of the listView properly formatted and populated. 如果我在锁定手机的情况下从android studio运行该项目,然后解锁手机,则该应用会在手机上打开,并且所有listView的格式均已正确设置并填充。

I feel like it's a race condition issue between the asynctask and the adapter, but I can't seem to resolve it. 我觉得这是asynctask和适配器之间的竞争条件问题,但我似乎无法解决。 I tried making my asyncTask an inner private class and calling notifyDataSetChanged on the adapter inside the onPostExecute method, but to no avail. 我尝试将asyncTask设置为内部私有类,并在onPostExecute方法内的适配器上调用notifyDataSetChanged ,但无济于事。 I feel it must be something simple, but I'm relatively new to Android dev, so I'm stuck. 我觉得它一定很简单,但是对于Android开发人员来说我还比较陌生,所以我很固执。

I have three classes that I'll post the pertinent code from 我有三个类,我将从中发布相关代码

MainActivity.java ( onCreate ) 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 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 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){

    }
}

Below are links to my screenshots showing the app not populating the listView, and the app working properly when the program is run while the phone is initially locked. 以下是我的屏幕快照的链接,其中显示了该应用程序未填充listView以及该应用程序在最初锁定手机时运行该程序时正常运行。

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

Any help would be greatly appreciated!! 任何帮助将不胜感激!!

Thanks 谢谢

In postExecute(), you need to update the adapter's List and then invoke its notifyDataSetChanged method. 在postExecute()中,您需要更新适配器的List,然后调用其notifyDataSetChanged方法。 I suspect that you were forgetting to update the adapter's data. 我怀疑您忘记了更新适配器的数据。

The other option is to create a new adapter with the new data, and set the new adapter on the ListView. 另一个选项是使用新数据创建一个新适配器,并在ListView上设置新适配器。

I figured out what the issue was! 我知道了问题所在! I hadn't added @Override to my onPostExecute() method so it was never being called. 我没有将@Override添加到我的onPostExecute()方法中,因此它从未被调用过。

I added the notifyDataSetChanged to my onPostExecute as suggested, which worked once I added the @override to my method. 我按照建议将notifyDataSetChanged添加到了onPostExecute,一旦将@override添加到我的方法中就可以使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM