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

标签 java android android-listview android-asynctask custom-adapter

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

我遇到的奇怪问题是,当我在 Android 手机上调试项目时,主要 Activity 是空白的,并且 listView 未填充。如果我在手机锁定的情况下从 android studio 运行该项目,然后解锁手机,应用程序将在我的手机上打开,并且所有 listView 的格式和填充均正确。

我觉得这是异步任务和适配器之间的竞争条件问题,但我似乎无法解决它。我尝试将 asyncTask 设为内部私有(private)类,并在 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,并且在手机最初锁定时运行程序时应用程序正常工作。

任何帮助将不胜感激!!

谢谢

最佳答案

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

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

关于java - Android 自定义适配器和 asyncTask 不更新 listView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28798681/

相关文章:

java - 上传文件到 FTP 服务器时出现异常

java - 如何为 Web 应用程序创建和使用自定义类的变量?

Java - 正则表达式 - 字母数字加/-

android - 写入文件并执行。 py文件在android python 3

android - android中自定义ArrayAdapter中的自定义getFilter

java - Swing JCheckbox 的多选问题

android - 如何在用户打开下一个 fragment 时停止 CountDownTimer 计数?

android - 如何知道手机或系统连接到我的 android 调制解调器?

android - 使用运行总计填充 CursorAdapter 的 ListView

android - ListView 可索引吗?