我正在尝试在 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
既然你说“我可以通过使用简单的 for 循环轻松地记录它”,数据似乎输入得很好。
就我而言,RecyclerView.ViewHolders 布局文件就是问题所在。 list_item 的根 viewGroup 的高度为 match_parent。这应该是wrap_content。
我可以检查一下你的布局文件吗?
问题是,我不断地只显示一条数据
是的。这是因为
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()));
但这不是温度..
您创建一个活动,然后发出网络请求,最终调用回调,并将结果发送到 RecyclerView 适配器。您声称回收视图没有显示这些项目。
潜在问题。
我想说你可以很容易地隔离 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 没问题,应该会显示...如果没有,那么你应该看看为什么。
如果问题已解决,现在开始调试何时/如何接收数据;使用调试器检查回调中的值;是否使用正确的数据调用适配器?
从那里开始。