簡體   English   中英

在customAdapter.notifyDataSetChanged之后ListView不更新

[英]ListView does not update after customAdapter.notifyDataSetChanged

在我的程序中,我試圖將天氣狀況列表更新為ListView。 我將JSON下載並存儲在asyncTask中,然后在onPostExecute和notifyDataSetChanged期間將數據解析到我的List中。 我在這里看了幾個相關的問題,但是不確定我缺少什么。 這是我的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_width="match_parent"
android:layout_height="match_parent">

<ImageView
    android:id="@+id/conditionImageView"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_weight="1"
    android:contentDescription="@string/weather_image"
    android:scaleType="fitCenter"
    app:srcCompat="@mipmap/ic_launcher_round" />

<GridLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:columnCount="3"
    android:rowCount="2"
    android:useDefaultMargins="true"
    android:visibility="visible">

    <TextView
        android:id="@+id/dayTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        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_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_column="0"
        android:layout_columnWeight="1"
        android:layout_row="1"
        android:text="@string/low" />

    <TextView
        android:id="@+id/highTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_column="2"
        android:layout_columnWeight="1"
        android:layout_row="1"
        android:text="@string/high" />

    <TextView
        android:id="@+id/humidityTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_column="1"
        android:layout_columnWeight="1"
        android:layout_row="1"
        android:text="@string/humidity" />

    <TextView
        android:id="@+id/timeOfDayTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_column="1"
        android:layout_columnWeight="1"
        android:layout_row="0"
        android:text="@string/time" />

    <TextView
        android:id="@+id/descriptionTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        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

不僅僅是添加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傳遞給您要充氣的布局。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM