在 customAdapter.notifyDataSetChanged 之后 ListView 不更新
Posted
技术标签:
【中文标题】在 customAdapter.notifyDataSetChanged 之后 ListView 不更新【英文标题】:ListView does not update after customAdapter.notifyDataSetChanged 【发布时间】:2018-03-17 21:24:18 【问题描述】:在我的程序中,我试图将天气状况列表更新为 ListView。我下载 JSON 并将其存储在 asyncTask 中,然后在 onPostExecute 和 notifyDataSetChanged 期间将数据解析到我的列表中。我在这里查看了几个相关的问题,但我不确定我错过了什么。这是我的 MainActivity.java
public class MainActivity extends AppCompatActivity
private List<Weather> weatherList = new ArrayList<>();
private WeatherArrayAdapter weatherArrayAdapter;
private ListView weatherListView;
private TextView locationEditText;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
weatherListView = (ListView)findViewById(R.id.weatherListView);
weatherArrayAdapter = new WeatherArrayAdapter(this, weatherList);
weatherListView.setAdapter(weatherArrayAdapter);
locationEditText = (TextView)findViewById(R.id.locationEditText);
fab.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
//Create a URL using the specific city entered by the user
URL url = createURL(locationEditText.getText().toString());
//As long as there is not a null url we get the weather
if(url!=null)
Log.e("URL", url.toString());
dismissKeyboard(locationEditText);
GetWeatherTask getLocalWeatherTask = new GetWeatherTask();
getLocalWeatherTask.execute(url);
else
Snackbar.make(findViewById(R.id.coordinatorLayout),R.string.invalid_url, Snackbar.LENGTH_LONG).show();
);
private void dismissKeyboard(View v)
InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
private URL createURL(String city)
String apiKey = getString(R.string.api_key);
String baseURL = getString(R.string.web_service_url);
try
String urlString = baseURL + URLEncoder.encode(city, "UTF-8") + "&units=imperial&cnt=16&APPID=" + apiKey;
return new URL(urlString);
catch (Exception e)
e.printStackTrace();
//Returns null only if the URL data was malformed
return null;
private class GetWeatherTask extends AsyncTask<URL, Void, JSONObject>
@Override
protected JSONObject doInBackground(URL... params)
HttpURLConnection connection = null;
try
URL url = params[0];
Log.e("URL", url.toString());
connection = (HttpURLConnection)url.openConnection();
int responseCode = connection.getResponseCode();
if(responseCode == 200)
StringBuilder stringBuilder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")))
String line;
while((line = bufferedReader.readLine()) != null)
stringBuilder.append(line);
connection.disconnect();
return new JSONObject(stringBuilder.toString());
catch (Exception e)
e.printStackTrace();
else
Snackbar.make(findViewById(R.id.coordinatorLayout), R.string.connect_fail, Snackbar.LENGTH_LONG).show();
catch (Exception e)
e.printStackTrace();
finally
if (connection != null)
connection.disconnect();
return null;
@Override
protected void onPostExecute(JSONObject weather)
convertJSONtoArrayList(weather);
weatherArrayAdapter.updateData(weatherList);
weatherArrayAdapter.notifyDataSetChanged();
weatherListView.smoothScrollToPosition(0);
private void convertJSONtoArrayList(JSONObject forecast)
weatherList.clear();
try
JSONArray list = forecast.getJSONArray("list");
for(int i = 0; i < list.length(); i++)
JSONObject day = list.getJSONObject(i);
JSONObject temperatures = day.getJSONObject("main");
JSONObject weather = day.getJSONArray("weather").getJSONObject(0);
Calendar hour = Calendar.getInstance();
hour.setTime(new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss", Locale.US).parse(day.getString("dt_txt")));
weatherList.add(new Weather(
day.getLong("dt")*1000,
hour.getTimeInMillis(),
temperatures.getDouble("temp_min"),
temperatures.getDouble("temp_max"),
temperatures.getDouble("humidity"),
weather.getString("icon"),
weather.getString("description")));
catch (Exception e)
e.printStackTrace();
这是我的 WeatherArrayAdapter.java
class WeatherArrayAdapter extends ArrayAdapter<Weather>
private static class ViewHolder
ImageView conditionImageView;
TextView dayTextView;
TextView lowTextView;
TextView highTextView;
TextView humidityTextView;
TextView timeOfDayTextView;
TextView descriptionTextView;
//Create a map of used bitmaps to prevent re-downloading previously used bitmaps
private Map<String, Bitmap> bitmaps = new HashMap<>();
private List<Weather> weatherList;
WeatherArrayAdapter(Context context, List<Weather> forecast)
super(context, R.layout.item_list, forecast);
this.weatherList = forecast;
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
Log.e("ADAPTER", "getView()");
Weather day = weatherList.get(position);
ViewHolder viewHolder;
if(convertView == null)
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.list_item, parent, false);
viewHolder.conditionImageView = convertView.findViewById(R.id.conditionImageView);
viewHolder.dayTextView = convertView.findViewById(R.id.dayTextView);
viewHolder.highTextView = convertView.findViewById(R.id.highTextView);
viewHolder.lowTextView = convertView.findViewById(R.id.lowTextView);
viewHolder.humidityTextView = convertView.findViewById(R.id.humidityTextView);
viewHolder.timeOfDayTextView = convertView.findViewById(R.id.timeOfDayTextView);
viewHolder.descriptionTextView = convertView.findViewById(R.id.descriptionTextView);
else
viewHolder = (ViewHolder) convertView.getTag();
if (bitmaps.containsKey(day.iconURL))
viewHolder.conditionImageView.setImageBitmap(bitmaps.get(day.iconURL));
else
new LoadImageTask(viewHolder.conditionImageView).execute(day.iconURL);
viewHolder.dayTextView.setText(day.dayOfWeek);
viewHolder.highTextView.setText(day.maxTemp);
viewHolder.lowTextView.setText(day.minTemp);
viewHolder.humidityTextView.setText(day.humidity);
viewHolder.timeOfDayTextView.setText(day.timeOfDay);
viewHolder.descriptionTextView.setText(day.description);
return convertView;
private class LoadImageTask extends AsyncTask<String, Void, Bitmap>
ImageView imageView;
LoadImageTask(ImageView view)
this.imageView = view;
@Override
protected Bitmap doInBackground(String... strings)
Bitmap bmp = null;
HttpURLConnection connection = null;
try
URL url = new URL(strings[0]);
connection = (HttpURLConnection)url.openConnection();
try(InputStream inputStream = connection.getInputStream())
bmp = BitmapFactory.decodeStream(inputStream);
bitmaps.put(strings[0], bmp);
catch (Exception e)
e.printStackTrace();
catch (Exception e)
e.printStackTrace();
finally
if (connection != null)
connection.disconnect();
return bmp;
@Override
protected void onPostExecute(Bitmap bitmap)
imageView.setImageBitmap(bitmap);
public void updateData(List<Weather> weatherList)
this.weatherList = weatherList;
Weather.java 类
class Weather
final String dayOfWeek, minTemp, maxTemp, humidity, iconURL, timeOfDay, description;
Weather(long timestamp, long timeOfDayMS, double minTemp, double maxTemp, double humidity, String iconName, String description)
NumberFormat numberFormat = NumberFormat.getNumberInstance();
numberFormat.setParseIntegerOnly(true);
this.dayOfWeek = convertTimestampToDay(timestamp);
this.timeOfDay = convertTimeOfDayToHM(timeOfDayMS);
this.minTemp = numberFormat.format(minTemp) + "\u00B0F";
this.maxTemp = numberFormat.format(maxTemp) + "\u00B0F";
this.humidity = numberFormat.format(humidity) + "%";
this.iconURL = "http://openweathermap.org/img/w/" + iconName + ".png";
this.description = description;
//Given a timestamp of milliseconds since epoch, we create a calendar and derive a day of the week name
private String convertTimestampToDay(long timestamp)
return new SimpleDateFormat("EEEE", Locale.US).format(getCalendar(timestamp).getTimeInMillis());
//Given a timestamp of milliseconds since epoch, we create a calendar and derive a time of day in hour:minute
private String convertTimeOfDayToHM(long timeOfDay)
return new SimpleDateFormat("h:mm a", Locale.US).format(getCalendar(timeOfDay).getTimeInMillis());
private Calendar getCalendar(long timestamp)
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
calendar.setTimeZone(TimeZone.getTimeZone(Calendar.getInstance().getTimeZone().getDisplayName()));
return calendar;
最后是我的 list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal" android:layout_
android:layout_>
<ImageView
android:id="@+id/conditionImageView"
android:layout_
android:layout_
android:layout_weight="1"
android:contentDescription="@string/weather_image"
android:scaleType="fitCenter"
app:srcCompat="@mipmap/ic_launcher_round" />
<GridLayout
android:layout_
android:layout_
android:layout_weight="1"
android:columnCount="3"
android:rowCount="2"
android:useDefaultMargins="true"
android:visibility="visible">
<TextView
android:id="@+id/dayTextView"
android:layout_
android:layout_
android:layout_column="0"
android:layout_columnWeight="1"
android:layout_row="0"
android:text="@string/day"
android:textAppearance="@android:style/TextAppearance.Material.Large" />
<TextView
android:id="@+id/lowTextView"
android:layout_
android:layout_
android:layout_column="0"
android:layout_columnWeight="1"
android:layout_row="1"
android:text="@string/low" />
<TextView
android:id="@+id/highTextView"
android:layout_
android:layout_
android:layout_column="2"
android:layout_columnWeight="1"
android:layout_row="1"
android:text="@string/high" />
<TextView
android:id="@+id/humidityTextView"
android:layout_
android:layout_
android:layout_column="1"
android:layout_columnWeight="1"
android:layout_row="1"
android:text="@string/humidity" />
<TextView
android:id="@+id/timeOfDayTextView"
android:layout_
android:layout_
android:layout_column="1"
android:layout_columnWeight="1"
android:layout_row="0"
android:text="@string/time" />
<TextView
android:id="@+id/descriptionTextView"
android:layout_
android:layout_
android:layout_column="2"
android:layout_columnWeight="1"
android:layout_row="0"
android:text="@string/desc" />
</GridLayout>
</LinearLayout>
非常感谢任何帮助。
编辑我已经修复了超级构造函数,我正在从服务器获取数据 不幸的是,我的列表视图仍然是空白的。 这是我从 API 获得的 JSON 日志。
D/JSON: "cod":"200","message":0.1604,"cnt":16,"list":["dt":1507280400,"main":"temp":52,"temp_min":50.88,"temp_max":52,"pressure":1031.72,"sea_level":1039.36,"grnd_level":1031.72,"humidity":70,"temp_kf":0.62,"weather":["id":800,"main":"Clear","description":"clear sky","icon":"01d"],"clouds":"all":0,"wind":"speed":8.84,"deg":325.503,"sys":"pod":"d","dt_txt":"2017-10-06 09:00:00","dt":1507291200,"main":"temp":56.17,"temp_min":55.34,"temp_max":56.17,"pressure":1032,"sea_level":1039.58,"grnd_level":1032,"humidity":65,"temp_kf":0.46,"weather":["id":800,"main":"Clear","description":"clear sky","icon":"01d"],"clouds":"all":0,"wind":"speed":8.95,"deg":326.001,"sys":"pod":"d","dt_txt":"2017-10-06 12:00:00","dt":1507302000,"main":"temp":57.13,"temp_min":56.58,"temp_max":57.13,"pressure":1031.96,"sea_level":1039.61,"grnd_level":1031.96,"humidity":57,"temp_kf":0.31,"weather":["id":800,"main":"Clear","description":"clear sky","icon":"01d"],"clouds":"all":0,"wind":"speed":8.08,"deg":321.001,"sys":"pod":"d","dt_txt":"2017-10-06 15:00:00","dt":1507312800,"main":"temp":51.49,"temp_min":51.22,"temp_max":51.49,"pressure":1031.85,"sea_level":1039.49,"grnd_level":1031.85,"humidity":63,"temp_kf":0.15,"weather":["id":803,"main":"Clouds","description":"broken clouds","icon":"04n"],"clouds":"all":64,"wind":"speed":3.71,"deg":290.502,"sys":"pod":"n","dt_txt":"2017-10-06 18:00:00","dt":1507323600,"main":"temp":46.91,"temp_min":46.91,"temp_max":46.91,"pressure":1031.69,"sea_level":1039.4,"grnd_level":1031.69,"humidity":81,"temp_kf":0,"weather":["id":801,"main":"Clouds","description":"few clouds","icon":"02n"],"clouds":"all":20,"wind":"speed":4.85,"deg":223.502,"sys":"pod":"n","dt_txt":"2017-10-06 21:00:00","dt":1507334400,"main":"temp":47.11,"temp_min":47.11,"temp_max":47.11,"pressure":1030.48,"sea_level":1038.22,"grnd_level":1030.48,"humidity":85,"temp_kf":0,"weather":["id":802,"main":"Clouds","description":"scattered clouds","icon":"03n"],"clouds":"all":32,"wind":"speed":7.74,"deg":249.001,"sys":"pod":"n","dt_txt":"2017-10-07 00:00:00","dt":1507345200,"main":"temp":48.53,"temp_min":48.53,"temp_max":48.53,"pressure":1028.24,"sea_level":1035.82,"grnd_level":1028.24,"humidity":78,"temp_kf":0,"weather":["id":802,"main":"Clouds","description":"scattered clouds","icon":"03n"],"clouds":"all":44,"wind":"speed":9.42,"deg":237.503,"sys":"pod":"n","dt_txt":"2017-10-07 03:00:00","dt":1507356000,"main":"temp":49.38,"temp_min":49.38,"temp_max":49.38,"pressure":1025.51,"sea_level":1033.19,"grnd_level":1025.51,"humidity":90,"temp_kf":0,"weather":["id":500,"main":"Rain","description":"light rain","icon":"10n"],"clouds":"all":88,"wind":"speed":13.04,"deg":237.506,"rain":"3h":0.715,"sys":"pod":"n","dt_txt":"2017-10-07 06:00:00","dt":1507366800,"main":"temp":55.61,"temp_min":55.61,"temp_max":55.61,"pressure":1023.56,"sea_level":1031.15,"grnd_level":1023.56,"humidity":89,"temp_kf":0,"weather":["id":500,"main":"Rain","description":"light rain","icon":"10d"],"clouds":"all":80,"wind":"speed":14.45,"deg":250.003,"rain":"3h":0.21,"sys":"pod":"d","dt_txt":"2017-10-07 09:00:00","dt":1507377600,"main":"temp":61.41,"temp_min":61.41,"temp_max":61.41,"pressure":1021.72,"sea_level":1029.22,"grnd_level":1021.72,"humidity":78,"temp_kf":0,"weather":["id":500,"main":"Rain","description":"light rain","icon":"10d"],"clouds":"all":76,"wind":"speed":14.79,"deg":265.003,"rain":"3h":0.145,"sys":"pod":"d","dt_txt":"2017-10-07 12:00:00","dt":1507388400,"main":"temp":62.38,"temp_min":62.38,"temp_max":62.38,"pressure":1020.3,"sea_level":1027.8,"grnd_level":1020.3,"humidity":69,"temp_kf":0,"weather":["id":500,"main":"Rain","description":"light rain","icon":"10d"],"clouds":"all":92,"wind":"speed":13.76,"deg":280,"rain":"3h":0.0049999999999999,"sys":"pod":"d","dt_txt":"2017-10-07 15:00:00","dt":1507399200,"main":"temp":59.14,"temp_min":59.14,"temp_max":59.14,"pressure":1020.7,"sea_level":1028.21,"grnd_level":1020.7,"humidity":69,"temp_kf
【问题讨论】:
【参考方案1】:不只是添加notifyDataSetChanged()
,而是将新的arraylist
作为方法传递给weatherArrayAdapter
,然后调用notifyDataSetChanged()
。
在您的 weatherArrayAdapter 类中创建这样的方法
public void updateData( List<Weather> weatherList )
this.weatherList=weatherList;
在你的 onPostEcecute 添加这个。
convertJSONtoArrayList(weather);
weatherArrayAdapter.updateData(weatherList);
weatherArrayAdapter.notifyDataSetChanged();
此外,您的预测列表不会在列表适配器代码中的任何地方使用。检查一次;
编辑:
您在构造函数中将布局的 id 作为 -1 传递super(context, -1, forecast)
。相反,您需要将 id 传递给您尝试膨胀的布局。
【讨论】:
我编辑了问题中的代码以反映这些更改,但我的 ListView 中仍然没有数据。 您没有在任何地方使用该列表......这就是它不显示数据的原因 代替这个 Weather day = getItem(position) 使用 Weather day = weatherList.get(position); 我改变了它,但它并没有解决问题。尝试在 WeatherArrayAdapter 的 getView 方法中记录任何内容都不会显示。这是正常现象还是问题的一部分? 您是否从服务器获取数据?使用日志检查..在此处发布日志以上是关于在 customAdapter.notifyDataSetChanged 之后 ListView 不更新的主要内容,如果未能解决你的问题,请参考以下文章
在 React 应用程序中在哪里转换数据 - 在 Express 中还是在前端使用 React?