我正在制作一个使用OWM 5天3小时预报API显示天气的android应用程序,该ui包含用于输入城市名称的EditText,用于启动通话过程的按钮,将显示5个条目(五天)和每天条目的列表视图包括另一个列表视图,该列表视图每天显示每3个小时的脱脂和温度,
我可以看到几天的列表视图,但是看不到每小时数据的嵌套列表视图。我的类包括:MainActivity,用于显示每小时3小时天气的WeatherAdapter,用于显示日期条目的DayAdapter以及JsonToWeather数据类,该数据类从Json响应中提取数据,并仅针对特定一天创建数据数组列表。我试图记录错误,并通过注释突出显示了错误位置。
主要活动 :

public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private String responseJSON = null;
ListView listView;
ArrayList<WeatherData> weatherDataArrayList;
WeatherAdapter weatherAdapter = null;
EditText cityName;
String city = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView = (ListView) findViewById(R.id.dayList);
    cityName = (EditText) findViewById(R.id.cityName);
    Button load = (Button) findViewById(R.id.loadButton);
    load.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            city = cityName.getText().toString();
            Log.d(TAG, "onClick: city is : " + city);
            if(city == null){
                Toast toast = null;
                toast.makeText(MainActivity.this,"Please Enter a city before continuing",Toast.LENGTH_LONG);
                toast.show();
            } else {

                String url = "http://api.openweathermap.org/data/2.5/forecast?q=" + (city.toLowerCase()) + "&units=metric&appid=8b10912e19fde267f36f6cb785ee7efd";

                Log.d(TAG, "onCreate: staring download task");
                DownloadJSON downloadJSON = new DownloadJSON();
                downloadJSON.execute(url);
                Log.d(TAG, "onCreate: after downloadtask");
            }
        }
    });


    if(weatherDataArrayList == null){
        Log.d(TAG, "onCreate: ArrayList is Still null");
    }
}

private class DownloadJSON extends AsyncTask<String, Void, String>{
    private static final String TAG = "DownloadJSON";

    private String downloadJSON(String url){
        StringBuilder jsonResult = new StringBuilder();
        try{
            URL apiURL = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) apiURL.openConnection();
            int responseCode = connection.getResponseCode();
            Log.d(TAG, "downloadJSON: Response code "+ responseCode);
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

            int charReader;
            char[] inputBuffer = new char[500];
            while(true){
                charReader = reader.read(inputBuffer);
                if(charReader < 0){
                    break;
                }
                if(charReader > 0){
                    jsonResult.append(String.copyValueOf(inputBuffer, 0, charReader));
                }
            }
            reader.close();
            return jsonResult.toString();
        }catch (MalformedURLException e){
            Log.e(TAG, "downloadJSON: URL is Invalid");
        }catch (IOException e){
            Log.e(TAG, "downloadJSON: IO Error");
        }
        return null;
    }

    @Override
    protected String doInBackground(String... strings) {
        Log.d(TAG, "doInBackground: url is : " + strings[0]);
        String jsonResponse = downloadJSON(strings[0]);
        if(jsonResponse == null){
            Log.e(TAG, "doInBackground: Error downloading");
        }
        return jsonResponse;
    }

    @Override
    protected void onPostExecute(String jsonResponse) {
        super.onPostExecute(jsonResponse);
        Log.d(TAG, "onPostExecute: json received is : " + jsonResponse);
        if(jsonResponse != null){
            JsonToWeatherData jtwd = new JsonToWeatherData();
            weatherDataArrayList = jtwd.extractor(jsonResponse);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            String date1 = simpleDateFormat.format(calendar.getTime());
            calendar.add(Calendar.DATE,1);
            String date2 = simpleDateFormat.format(calendar.getTime());
            calendar.add(Calendar.DATE,1);
            String date3 = simpleDateFormat.format(calendar.getTime());
            calendar.add(Calendar.DATE,1);
            String date4 = simpleDateFormat.format(calendar.getTime());
            calendar.add(Calendar.DATE,1);
            String date5 = simpleDateFormat.format(calendar.getTime());
            ArrayList<String> days = new ArrayList<>();
            days.add(date1);
            days.add(date2);
            days.add(date3);
            days.add(date4);
            days.add(date5);
            DayAdapter day = new DayAdapter(MainActivity.this,R.layout.layout_day_card,days,weatherDataArrayList);
            listView.setAdapter(day);
        } else {
            Log.d(TAG, "onPostExecute: no json recieved, city is Wrong");
            Toast toast = Toast.makeText(MainActivity.this,"Please provide a valid city!",Toast.LENGTH_LONG);
            toast.show();
        }
    }

}
}

WeatherAdapter :
public class WeatherAdapter extends ArrayAdapter<WeatherData> {
private static final String TAG = "WeatherAdapter";
private final int layoutResourceID;
private LayoutInflater layoutInflater;
private ArrayList<WeatherData> block;

public WeatherAdapter(@NonNull Context context, int resource, ArrayList<WeatherData> block) {
    super(context, resource, block);
    this.layoutResourceID = resource;
    this.block = block;
    this.layoutInflater = LayoutInflater.from(context);
    Log.d(TAG, "WeatherAdapter: called constructor");
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    if(convertView == null){
        convertView = layoutInflater.inflate(layoutResourceID,parent,false);
    }
    Log.d(TAG, "getView: entered");
    WeatherData weatherData = block.get(position);
    TextView temp = (TextView) convertView.findViewById(R.id.temperature);
    temp.setText(weatherData.getTemp());
    TextView shortDesc = (TextView) convertView.findViewById(R.id.descrip);
    shortDesc.setText(weatherData.getShortDesc());
    return convertView;
}
}

DayAdapter :
public class DayAdapter extends ArrayAdapter<String> {
private static final String TAG = "DayAdapter";
private ArrayList<String> dayBlock;
private LayoutInflater layoutInflater;
private int layoutresourceID;
private ArrayList<WeatherData> dayWeather, fullBlock;
private Context context;
JsonToWeatherData json = new JsonToWeatherData();

public DayAdapter(@NonNull Context context, int resource, @NonNull ArrayList<String> dayBlock, ArrayList<WeatherData> weatherBlock) {
    super(context, resource, dayBlock);
    this.context = context;
    this.dayBlock = dayBlock;
    this.fullBlock = weatherBlock;
    layoutInflater = LayoutInflater.from(context);
    this.layoutresourceID = resource;
    if(fullBlock == null){
        Log.e(TAG, "DayAdapter: full block is null");
    }
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    if (convertView == null){
        convertView = layoutInflater.inflate(layoutresourceID,parent,false);
    }
    TextView date = (TextView) convertView.findViewById(R.id.date);
    TextView minTempFoDay = (TextView) convertView.findViewById(R.id.minTempOfDay);
    TextView maxTempFoDay = (TextView) convertView.findViewById(R.id.maxTempOfDay);
    ListView weatherHolderListView = (ListView) convertView.findViewById(R.id.wHoldLV);
    String dateString = dayBlock.get(position);
    dayWeather = json.extractByDate(fullBlock,dateString);
    if(fullBlock == null){
        Log.d(TAG, "getView: fullblock is null");
    }
    if(dayWeather == null){
        Log.d(TAG, "getView: dayweather array is null");
    } else {
        Log.d(TAG, "getView: dayweather is not null");
    }
    String test = dayWeather.get(position).getTemp(); // error occured here
    Log.d(TAG, "getView: test string : " + test);
    date.setText(dateString);
    DecimalFormat df = new DecimalFormat(".##");
    float mint = 500, maxt = 0;
    String mint1 = "", maxt1 = "";
    for(WeatherData data : dayWeather){
        if(mint > Float.parseFloat(data.getMinTemp())){
            mint = Float.parseFloat(data.getMinTemp());
            mint1 = df.format(mint);
            Log.d(TAG, "getView: mint : " + mint);
        }
        if (maxt > Float.parseFloat(data.getMaxTemp())){
            maxt = Float.parseFloat(data.getMaxTemp());
            maxt1 = df.format(maxt);
        }
    }
    minTempFoDay.setText(mint1);
    maxTempFoDay.setText(maxt1);
    WeatherAdapter weatherAdapter = new WeatherAdapter(context,R.layout.weather_holder,dayWeather);
    weatherHolderListView.setAdapter(weatherAdapter);

    return convertView;
}
}

JsonToWeatherData:
public class JsonToWeatherData {
private static final String TAG = "JsonToWeatherData";

public ArrayList<WeatherData> extractor(String jsonData){
    Log.d(TAG, "extractor: in the method");
    if(jsonData == null){
        return null; // if there is no json data is received
    } else {
        ArrayList<WeatherData> weatherDataArrayList = new ArrayList<WeatherData>();
        Log.d(TAG, "extractor: in the else field");
        try{
            Log.d(TAG, "extractor: in try block");
            JSONObject root = new JSONObject(jsonData);
            int count = root.getInt("cnt");
            JSONArray wList = root.getJSONArray("list");
            for (int i = 0; i < count; ++i){
                WeatherData weather = new WeatherData();
                JSONObject wBlock = wList.getJSONObject(i);
                weather.setDate(wBlock.getString("dt_txt"));
                JSONObject mainObj = wBlock.getJSONObject("main");
                weather.setTemp(String.valueOf(mainObj.getDouble("temp")));
                weather.setMinTemp(String.valueOf(mainObj.getDouble("temp_min")));
                weather.setMaxTemp(String.valueOf(mainObj.getDouble("temp_max")));
                weather.setHumidity(String.valueOf(mainObj.getInt("humidity")));
                JSONArray warray = wBlock.getJSONArray("weather");
                JSONObject weatherObj = warray.getJSONObject(0);
                weather.setDescription(weatherObj.getString("description"));
                weather.setShortDesc(weatherObj.getString("main"));
                weather.setIconID(weatherObj.getString("icon"));
                weatherDataArrayList.add(weather);
                Log.d(TAG, "extractor: temp field is :" + weather.getTemp());
            }
        }catch (JSONException e){
            e.printStackTrace();
        }
        return weatherDataArrayList;
    }
}

public ArrayList<WeatherData> extractByDate(ArrayList<WeatherData> fullList,String date){
    ArrayList<WeatherData> dayweatherList = new ArrayList<WeatherData>();
    for( WeatherData weather : fullList ){
        if( ( weather.getDate().substring(0,9) ).equals(date) ){
            dayweatherList.add(weather);
        }
    }
    return dayweatherList;
}
}


我该怎么办?

错误信息 : (
        08-19 23:11:39.914 12148-12148 / com.jugalmistry.apps.fivedaysofweather D / DayAdapter:getView:dayweather不为空
    08-19 23:11:39.916 12148-12148 / com.jugalmistry.apps.fivedaysofweather D / AndroidRuntime:关闭VM
    08-19 23:11:39.918 12148-12148 / com.jugalmistry.apps.fivedaysofweather E / AndroidRuntime:FATAL EXCEPTION:main
        流程:com.jugalmistry.apps.fivedaysofweather,PID:12148
        java.lang.IndexOutOfBoundsException:索引:0,大小:0
            在java.util.ArrayList.get(ArrayList.java:411)
            在com.jugalmistry.apps.fivedaysofweather.DayAdapter.getView(DayAdapter.java:58)

最佳答案

我试图用下面的完整代码来帮助您。

我还建议您实施ViewHolder模式ViewHolder pattern example以提高性能。

public class MainActivity extends AppCompatActivity
{
    private static final String TAG = "MainActivity";

    EditText cityName;
    String city = null;

    ListView dayListView;
    ArrayList<WeatherData> weatherDataArrayList;

    DayAdapter dayAdapter;
    //private String responseJSON = null;
    //WeatherAdapter weatherAdapter = null; // Creating this adapter within the DayAdapter

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        cityName = (EditText) findViewById(R.id.cityName);
        Button load = (Button) findViewById(R.id.loadButton);

        dayListView = (ListView) findViewById(R.id.dayList);

        load.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                city = cityName.getText().toString();
                Log.d(TAG, "onClick: city is : " + city);
                if (city == null)
                {
                    Toast toast = null;
                    toast.makeText(MainActivity.this,"Please Enter a city before continuing",Toast.LENGTH_LONG);
                    toast.show();
                }
                else
                {
                    String url = "http://api.openweathermap.org/data/2.5/forecast?q=" + (city.toLowerCase()) + "&units=metric&appid=8b10912e19fde267f36f6cb785ee7efd";

                    Log.d(TAG, "onCreate: staring download task");
                    DownloadJSON downloadJSON = new DownloadJSON();
                    downloadJSON.execute(url);
                    Log.d(TAG, "onCreate: after downloadtask");
                }
            }
        });
    }

    public void SetDayListData(ArrayList<String> dayBlock, ArrayList<WeatherData> weatherBlock)
    {
        if (dayAdapter == null)
        {
            dayAdapter = new DayAdapter(MainActivity.this,R.layout.layout_day_card, days, weatherDataArrayList);
            dayListView.setAdapter(dayAdapter);
        }
        else
        {
            //created a new method "UpdateData" just to update the data in the adapter
            dayAdapter.UpdateData(days, weatherDataArrayList);
            dayAdapter.notifyDataSetChanged();
        }
    }

    private class DownloadJSON extends AsyncTask<String, Void, String>
    {
        private static final String TAG = "DownloadJSON";

        private String downloadJSON(String url)
        {
            StringBuilder jsonResult = new StringBuilder();

            try
            {
                URL apiURL = new URL(url);
                HttpURLConnection connection = (HttpURLConnection) apiURL.openConnection();
                int responseCode = connection.getResponseCode();
                Log.d(TAG, "downloadJSON: Response code "+ responseCode);
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

                int charReader;
                char[] inputBuffer = new char[500];
                while (true)
                {
                    charReader = reader.read(inputBuffer);
                    if (charReader < 0)
                    {
                        break;
                    }
                    if (charReader > 0)
                    {
                        jsonResult.append(String.copyValueOf(inputBuffer, 0, charReader));
                    }
                }
                reader.close();
                return jsonResult.toString();
            }
            catch (MalformedURLException e)
            {
                Log.e(TAG, "downloadJSON: URL is Invalid");
            }
            catch (IOException e)
            {
                Log.e(TAG, "downloadJSON: IO Error");
            }
            return null;
        }

        @Override
        protected String doInBackground(String... strings)
        {
            Log.d(TAG, "doInBackground: url is : " + strings[0]);
            String jsonResponse = downloadJSON(strings[0]);
            if (jsonResponse == null)
            {
                Log.e(TAG, "doInBackground: Error downloading");
            }
            return jsonResponse;
        }

        @Override
        protected void onPostExecute(String jsonResponse)
        {
            super.onPostExecute(jsonResponse);

            Log.d(TAG, "onPostExecute: json received is : " + jsonResponse);
            if (jsonResponse != null)
            {
                JsonToWeatherData jtwd = new JsonToWeatherData();
                weatherDataArrayList = jtwd.extractor(jsonResponse);
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                Calendar calendar = Calendar.getInstance();
                String date1 = simpleDateFormat.format(calendar.getTime());
                calendar.add(Calendar.DATE,1);
                String date2 = simpleDateFormat.format(calendar.getTime());
                calendar.add(Calendar.DATE,1);
                String date3 = simpleDateFormat.format(calendar.getTime());
                calendar.add(Calendar.DATE,1);
                String date4 = simpleDateFormat.format(calendar.getTime());
                calendar.add(Calendar.DATE,1);
                String date5 = simpleDateFormat.format(calendar.getTime());
                ArrayList<String> days = new ArrayList<>();
                days.add(date1);
                days.add(date2);
                days.add(date3);
                days.add(date4);
                days.add(date5);

                SetDayListData(days, weatherDataArrayList);
            }
            else
            {
                Log.d(TAG, "onPostExecute: no json recieved, city is Wrong");
                Toast toast = Toast.makeText(MainActivity.this,"Please provide a valid city!",Toast.LENGTH_LONG);
                toast.show();
            }
        }
    }
}

public class DayAdapter extends ArrayAdapter<String>
{
    private static final String TAG = "DayAdapter";

    private Context context;

    private LayoutInflater layoutInflater;
    private int layoutresourceID;

    private ArrayList<String> dayBlock;
    private ArrayList<WeatherData> dayWeather, weatherBlock;

    JsonToWeatherData json = new JsonToWeatherData();

    public DayAdapter(@NonNull Context context, int resource, @NonNull ArrayList<String> dayBlock, ArrayList<WeatherData> weatherBlock)
    {
        super(context, resource, dayBlock);
        this.context = context;
        this.dayBlock = dayBlock;
        this.weatherBlock = weatherBlock;
        layoutInflater = LayoutInflater.from(context);
        this.layoutresourceID = resource;

        if (weatherBlock == null)
        {
            Log.e(TAG, "DayAdapter: full block is null");
        }
    }

    @Override
    public int getCount()
    {
        return dayBlock.getSize();
    }

    public void UpdateData(@NonNull ArrayList<String> dayBlock, ArrayList<WeatherData> weatherBlock)
    {
        this.dayBlock = dayBlock;
        this.weatherBlock = weatherBlock;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
    {
        if (convertView == null)
        {
            convertView = layoutInflater.inflate(layoutresourceID,parent,false);
        }

        if (weatherBlock == null)
        {
            Log.d(TAG, "getView: weatherBlock is null");
            return convertView;
        }

        TextView date = (TextView) convertView.findViewById(R.id.date);
        TextView minTempFoDay = (TextView) convertView.findViewById(R.id.minTempOfDay);
        TextView maxTempFoDay = (TextView) convertView.findViewById(R.id.maxTempOfDay);
        ListView weatherHolderListView = (ListView) convertView.findViewById(R.id.wHoldLV);

        String dateString = dayBlock.get(position);
        dayWeather = json.extractByDate(weatherBlock, dateString);

        if (dayWeather == null)
        {
            Log.d(TAG, "getView: dayweather array is null");
            return convertView;
        }

        if (position > dayWeather.getSize() - 1)
        {
            Log.d(TAG, "getView: the position is too great for the dayWeather array");
            return convertView;
        }

        String test = dayWeather.get(position).getTemp(); // error occured here
        Log.d(TAG, "getView: test string : " + test);

        date.setText(dateString);

        DecimalFormat df = new DecimalFormat(".##");
        float mint = 500, maxt = 0;
        String mint1 = "", maxt1 = "";

        for (WeatherData data : dayWeather)
        {
            if (mint > Float.parseFloat(data.getMinTemp()))
            {
                mint = Float.parseFloat(data.getMinTemp());
                mint1 = df.format(mint);
                Log.d(TAG, "getView: mint : " + mint);
            }

            if (maxt > Float.parseFloat(data.getMaxTemp()))
            {
                maxt = Float.parseFloat(data.getMaxTemp());
                maxt1 = df.format(maxt);
            }
        }

        minTempFoDay.setText(mint1);
        maxTempFoDay.setText(maxt1);

        WeatherAdapter weatherAdapter = new WeatherAdapter(context, R.layout.weather_holder, dayWeather);
        weatherHolderListView.setAdapter(weatherAdapter);

        return convertView;
    }
}

关于java - ListView 内的 ListView 不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51920488/

10-09 08:11