java - 对非静态字段和 JSON 对象感到困惑

标签 java android android-studio

我正在学习如何使用 REST API,方法是制作一个使用雅虎天气显示今天天气的应用程序。我制作了一个 AsyncTask、一个自定义适配器和一个我在 MainActivity 中调用的 WeatherData 类。不过,我在使用这个 WeatherData 类和自定义适配器时遇到了一些麻烦。

在适配器中,当我尝试从天气数据类调用 JSON 对象时出现错误。它表示不能从静态上下文中引用非静态字段“天气”和“日期”。我试图阅读静态上下文,但它真的让我困惑它是什么以及它做了什么。

第二个问题是,当我尝试将日期和天气添加到天气数据 ArrayList 时,我的 AsyncTask 现在也会出错。它说 WeatherData 中的 WeatherData(JSONobject) 不能应用于 JSONObject,java.lang.String。我认为这与我在 WeatherData 类中使用天气和日期作为对象,然后尝试将它们用作数组列表中的字符串有关。我试图通过简单地将它们更改为 WeatherData 类中的字符串来修复它,但随后我遇到了各种新错误。有人可以帮我解决我哪里出错了吗?

所以,这是我调用数据的 MainActivity 的一部分:

public void getData(View view) {
    ClassAsyncTask task = new ClassAsyncTask(this);
    task.execute(chosenloc);
}

public void setData(ArrayList<WeatherData> weatherdata) {
    // Construct the data source
    ArrayList<WeatherData> arrayOfWeather = new ArrayList<WeatherData>();
    // Create the adapter to convert the array to views
    CustomArrayAdapter adapter = new CustomArrayAdapter(this, arrayOfWeather);
    // Attach the adapter to a Listview
    ListView listView = (ListView) findViewById(R.id.weatherListView);
    listView.setAdapter(adapter);
}

这是我的自定义适配器:

public class CustomArrayAdapter extends ArrayAdapter<WeatherData> {
public CustomArrayAdapter(Context context, ArrayList<WeatherData> weatherdata){
    super(context, 0, weatherdata);
}

@Override
public View getView(int position, View convertView, ViewGroup parent){
    // Get the data item for this position
    WeatherData weather = getItem(position);
    // Check if an exising view is being reused, otherwise inflate the view
    if (convertView == null){
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_array_layout, parent, false);
    }
    // Lookup view for data population
    TextView date = (TextView) convertView.findViewById(R.id.date);
    TextView weather = (TextView) convertView.findViewById(R.id.weather);

    // Populate the data into the template view using the data object
    date.setText(WeatherData.date);
    weather.setText(WeatherData.weather);

    // Return the completed view to render on screen
    return convertView;
}
}

我的 WeatherData 类:

public class WeatherData {
// Fields
public JSONObject date;
public String weather;

// Constructor
public WeatherData(JSONObject object) {
    try {
        JSONArray dates = object.getJSONArray("date");
        JSONArray weather = object.getJSONArray("text");
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
    // Method to convert an array of JSON objects into a list of objects
    public static ArrayList<WeatherData> fromJson(JSONArray jsonObjects){
        ArrayList<WeatherData> weather = new ArrayList<WeatherData>();
        for (int i = 0; i < jsonObjects.length(); i++) {
            try {
                weather.add(new WeatherData(jsonObjects.getJSONObject(i)));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return weather;
    }
}

最后,我在 AsyncTask 中解析 JSON 的部分:

protected void onPostExecute(String result){
    super.onPostExecute(result);

    // Alert user if nothing was found
    if(result.length() == 0){
        Toast.makeText(context, "Nothing was found", Toast.LENGTH_SHORT).show();
    }
    else {
        // Parse JSON
        ArrayList<WeatherData> weatherdata = new ArrayList<>();
        try {
            JSONObject respObj = new JSONObject(result);
            JSONObject forecastObj = respObj.getJSONObject("forecast");
            JSONArray dates = forecastObj.getJSONArray("date");
            JSONArray weatherArray = forecastObj.getJSONArray("text");

            for (int i = 0; i<dates.length(); i++){
                JSONObject date = dates.getJSONObject(i);
                String weather = date.getString("text");
                weatherdata.add(new WeatherData(date, weather));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        // Update MainActivity
        this.activity.setData(weatherdata);
    }
}

最佳答案

你有很多语义错误,了解静态和非静态的差异和细微差别非常重要,但要修复你的代码,只需注意你在何处使用的变量即可。我不会为您通读 Yahoo weather API,所以我在这里以通用方式展示一些内容。

固定代码如下:

这应该是你的 getView

// Get the data item for this position
WeatherData weather = getItem(position);
// Check if an exising view is being reused, otherwise inflate the view
if (convertView == null){
    convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_array_layout, parent, false);
}
// CHANGED HERE the textView "weather` had the same name of the "WeatherData" defined a few lines above
// Lookup view for data population
TextView textDate = (TextView) convertView.findViewById(R.id.date);
TextView textWeather = (TextView) convertView.findViewById(R.id.weather);

// CHANGED HERE to properly call the textView methods and to read the fields from the instance of "WeatherData"
// Populate the data into the template view using the data object
textDate.setText(weather.date);
textWeather.setText(weather.weather);

// Return the completed view to render on screen
return convertView;

您的“WeatherData”构造函数也是不合逻辑的,会导致 NPE。我不知道你想在那里实现什么,但是当你写 JSONArray dates = object... 时您提取的信息正在添加到此 JsonArray然后它被扔掉了。领域public JSONObject datepublic String weather从未被初始化并且不包含任何有用的信息。你可能想要做的是这样的事情:

// Fields
public String val1;
public String val2;
public String val3;
  ... any value necessary

// Constructor
public WeatherData(JSONObject object) {
    try {
         val1 = object.optString("val1");
         val2 = object.optString("val2");
         val3 = object.optString("val3");
        ... parse here EVERYTHING from the object
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

另外,在您的 postExecute 上你正在尝试创建新的 WeatherData传递两个值给它,像这样 new WeatherData(date, weather) .再次阅读 WeatherData构造函数,它只使用 1 个值,即 JsonObject object .

最后一个是表演,你不应该返回string到你的 onPostExecute。您应该执行一个返回 ArrayList<WeatherData> result 的 AsyncTask .那么所有的解析代码应该在background中执行。

编辑示例asyncTask

   public class MyAsyncTask extends AsyncTask<String, Integer, List<WeatherObject>>{

      @Override protected List<WeatherObject> doInBackground(String... params) {
         // here you call the API and parse the results
         // return ArrayList<WeatherObject> if successful, or `null` if failed
         return null;
      }

      @Override protected void onPostExecute(List<WeatherObject> weatherObjectList) {
           // here you simply check for null and use the List
           if(weatherObjectList == null){
               // fail to load data
           } else {
               // set data to adapter
           }
      }
   }

关于java - 对非静态字段和 JSON 对象感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36101895/

相关文章:

java - 如何从 CustomAdapter 将 textColor 设置为 edittext

android - 如何以编程方式检查 MIUI 自动启动权限?

android-studio - Android Studio 不会更新,说已经是最新版本

java - 更新 Android Studio 后膨胀类 CollapsingToolbarLayout 时出错

java - 如何制作正则表达式以查看字符串是否包含某个字母

Android:如何扭曲图像?

java - 使用 jpa(MYSQL) 创建一对多关系

android-studio - Android Studio 2.3.3 中 'Captures' 选项卡的用途是什么?

java - jar:在 Bash 中找不到命令

java - @embeddable 与 @entity 用于映射集合