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

Posted

技术标签:

【中文标题】Android自定义适配器和asyncTask不更新listView【英文标题】:Android custom adapter and asyncTask not updating listView 【发布时间】:2015-05-02 03:34:41 【问题描述】:

我搜索了所有我能找到的帖子,但似乎没有一个对我的情况有帮助。我有一个 android 项目,它使用 Web 服务来提取每小时的天气数据并用结果填充 listView。

我遇到的奇怪问题是,当我在我的 android 手机上调试项目时,主要活动是空白的,并且没有填充 listView。如果我在手机锁定的情况下从 android studio 运行项目,然后解锁手机,则应用会在我的手机上打开,并且所有 listView 都已正确格式化和填充。

我觉得这是 asynctask 和适配器之间的竞争条件问题,但我似乎无法解决它。我尝试将我的 asyncTask 设为内部私有类并在 onPostExecute 方法内的适配器上调用 notifyDataSetChanged,但无济于事。我觉得这一定很简单,但我对 Android 开发人员比较陌生,所以我被卡住了。

我有三个课程,我将从中发布相关代码

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;
    


下载WeatherTask.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,并且在手机最初锁定时运行程序时应用程序正常工作。

任何帮助将不胜感激!

谢谢

【问题讨论】:

【参考方案1】:

在 postExecute() 中,您需要更新适配器的 List,然后调用其 notifyDataSetChanged 方法。我怀疑您忘记更新适配器的数据。

另一个选项是使用新数据创建一个新适配器,并在 ListView 上设置新适配器。

【讨论】:

我不确定如何从 asyncTask 访问适配器。我尝试将 Async 类设为子类并以这种方式进行操作,并将其作为参数传递给我的 async 类,但均未奏效。 我会将它传递给 AsyncTask 的构造函数【参考方案2】:

我发现了问题所在!我没有将 @Override 添加到我的 onPostExecute() 方法中,所以它永远不会被调用。

我按照建议将 notifyDataSetChanged 添加到我的 onPostExecute 中,一旦我将 @override 添加到我的方法中,它就起作用了。

【讨论】:

以上是关于Android自定义适配器和asyncTask不更新listView的主要内容,如果未能解决你的问题,请参考以下文章

如何从android中的自定义适配器调用Activity asynctask

AsyncTask 在自定义适配器中不起作用

当 AsyncTask 在适配器内时刷新 ListView

Asynctask 和 RecyclerView 适配器中的 Android ProgressDialog

BaseAdapter 类不会在 Asynctask 中设置适配器 - Android

android listview 适配器 asynctask 图像加载