无法在RecyclerView中显示所有给定数据

问题描述 投票:0回答:3

我正在尝试在 RecyclerView 中显示来自预测 api 的数据。问题是,我不断地只显示一条数据——来自 api 的第一个数据,但应该还有更多。我可以使用简单的 for 循环轻松记录它。我已经几乎没有想法应该在这里改变什么......你能以某种方式帮助我吗?

主要活动

    public class MainActivity extends AppCompatActivity {
    public static final String BASE_URL = "https://api.openweathermap.org/";
    List<ModelClass> mTestData;
    ForecastAdapter mAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTestData = new ArrayList<>();

        RecyclerView recyclerView = findViewById(R.id.main_rv);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        mAdapter = new ForecastAdapter(mTestData);
        recyclerView.setAdapter(mAdapter);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiInterface apiInterface = retrofit.create(ApiInterface.class);

        Call<ModelClass> getForecastData = apiInterface.getForecastData(36, 137, "api_key_here");
        getForecastData.enqueue(new Callback<ModelClass>() {
            @Override
            public void onResponse(Call<ModelClass> call, Response<ModelClass> response) {
                Log.i(TAG, "onResponse: "+response.code());

                mTestData = Collections.singletonList(response.body());
                mAdapter.setData123(mTestData);
            }

            @Override
            public void onFailure(Call<ModelClass> call, Throwable t) {
                Log.i(TAG, "onFailure: " + t.getMessage());
            }
        });
    }
}

适配器

    public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.ViewHolder> {
    private List<ModelClass> mForecastData = new ArrayList<>();
    private static final String TAG = "ForecastAdapter";

    public ForecastAdapter(List<ModelClass> mForecastData) {
        this.mForecastData = mForecastData;
    }

    public void setData123(List<ModelClass> data){
        this.mForecastData = data;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);

        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.mTemperature.setText(String.valueOf(mForecastData.get(position).getForecastData().get(position)
        .getDatetime()));
        Log.i(TAG, "onBindViewHolder: "+mForecastData.get(position).getForecastData().get(position).getDatetime());
    }

    @Override
    public int getItemCount() {
        return mForecastData.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView mTemperature, mPressure;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            mTemperature = (TextView) itemView.findViewById(R.id.list_temperature);
            mPressure = (TextView) itemView.findViewById(R.id.list_pressure);
        }
    }
}

模型类

public class ModelClass {
    @SerializedName("cod")
    private int requestCode;
    @SerializedName("list")
    List<ForecastList> forecastData = new ArrayList<>();

    public List<ForecastList> getForecastData() {
        return forecastData;
    }


    public class ForecastList {
        @SerializedName("dt")
        private int datetime;
        @SerializedName("main")
        MainData mainData = null;

        public MainData getMainData() {
            return mainData;
        }

        public int getDatetime() {
            return datetime;
        }

        public class MainData {
            @SerializedName("temp")
            private double temperature;

            public double getTemperature() {
                return temperature;
            }
        }
    }
}

api接口

  public interface ApiInterface {
    @GET("data/2.5/forecast?")
    Call<ModelClass> getForecastData(
            @Query("lat") int lat,
            @Query("lon") int lon,
            @Query("appid") String api_key);
}

json 响应示例

{
  "cod": "200",
  "message": 0,
  "cnt": 40,
  "list": [
    {
      "dt": 1596564000,
      "main": {
        "temp": 293.55,
        "feels_like": 293.13,
        "temp_min": 293.55,
        "temp_max": 294.05,
        "pressure": 1013,
        "sea_level": 1013,
        "grnd_level": 976,
        "humidity": 84,
        "temp_kf": -0.5
      },
      "weather": [
        {
          "id": 500,
          "main": "Rain",
          "description": "light rain",
          "icon": "10d"
        }
      ],
      "clouds": {
        "all": 38
      },
      "wind": {
        "speed": 4.35,
        "deg": 309,
        "gust": 7.87
      },
      "visibility": 10000,
      "pop": 0.49,
      "rain": {
        "3h": 0.53
      },
      "sys": {
        "pod": "d"
      },
      "dt_txt": "2020-08-04 18:00:00"
    },

    ...

"city": {
    "id": 2643743,
    "name": "London",
    "coord": {
      "lat": 51.5073,
      "lon": -0.1277
    },
    "country": "GB",
    "timezone": 0,
    "sunrise": 1578384285,
    "sunset": 1578413272
  }
}
        

MainActivity.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/main_rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"/>

</LinearLayout>

list_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_parent"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/list_temperature"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="15dp"
        android:background="#bbbbbb"/>

    <TextView
        android:id="@+id/list_pressure"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="15dp"/>

</LinearLayout>

如何记录改造响应中的值

for(ModelClass modelClass : mTestData){
                Log.i(TAG, "onResponse: "+modelClass.getForecastData().get(0).getDatetime());
                Log.i(TAG, "onResponse: "+modelClass.getForecastData().get(1).getDatetime());
                Log.i(TAG, "onResponse: "+modelClass.getForecastData().get(2).getDatetime());
            }
...

控制台输出:

    2022-03-08 12:22:37.252 10032-10032/com.example.retrofittest I/ContentValues: onResponse: 1646740800
2022-03-08 12:22:37.252 10032-10032/com.example.retrofittest I/ContentValues: onResponse: 1646751600
2022-03-08 12:22:37.252 10032-10032/com.example.retrofittest I/ContentValues: onResponse: 1646762400
java android retrofit
3个回答
0
投票

既然你说“我可以通过使用简单的 for 循环轻松地记录它”,数据似乎输入得很好。

就我而言,RecyclerView.ViewHolders 布局文件就是问题所在。 list_item 的根 viewGroup 的高度为 match_parent。这应该是wrap_content。

我可以检查一下你的布局文件吗?


0
投票

问题是,我不断地只显示一条数据

是的。这是因为

public int getItemCount()
返回值 1,因为这是 ModelClass 列表的大小:
return mForecastData.size()

您只能从 Web 服务中获取一项 ModelClass 项目。

您最好返回类似以下内容:

return mForecastData.get(0).mTestData.size();

holder.mTemperature.setText(String.valueOf(mForecastData.get(position).getForecastData().get(position).getDatetime()));

更改为:

     holder.mTemperature.setText(String.valueOf(mForecastData.get(0).getForecastData().get(position).getDatetime()));

但这不是温度..


0
投票

您创建一个活动,然后发出网络请求,最终调用回调,并将结果发送到 RecyclerView 适配器。您声称回收视图没有显示这些项目。

潜在问题。

  1. RecyclerView 布局和/或其视图持有者是错误的(在 XML 中)。
  2. 适配器编码不正确。
  3. 网络请求错误/失败
  4. 代码的组合方式不正确,事情没有按照您期望的顺序发生。

我想说你可以很容易地隔离 1 和 2。

不要发出网络请求,而是创建一个简单的类(注意:为了简洁起见,我将使用 kotlin):


class FakeDataRepository {
  fun getData(): List<ModelClass> = listOf(...) //TODO: create a couple of fake/hardcoded items pretending they come from the API
}

现在不要在您的活动中调用改造,而是

result = FakeDataRepository().getData()

然后将

result
传递给您的适配器。

如果你的 RecyclerView 没问题,应该会显示...如果没有,那么你应该看看为什么。

如果问题已解决,现在开始调试何时/如何接收数据;使用调试器检查回调中的值;是否使用正确的数据调用适配器?

从那里开始。

© www.soinside.com 2019 - 2024. All rights reserved.