英文:
How to show a RecyclerView (with data fetched from API) as a list item in another RecyclerView in android?
问题
想要实现的目标是:一个聊天机器人,当用户输入单词“weather”时,在外部 RecyclerView 中的聊天项内返回一个作为 RecyclerView 的天气预报。
我希望天气信息成为实际的聊天项。
我有一个处理消息的 MessageAdapter 和一个处理天气预报信息的 WeatherAdapter,但在 MessageAdapter 的 onBindViewHolder 中处理“返回天气预报”情况时遇到了困难。
我尝试了许多不同的方法,但都无济于事:
使用 ConcatAdapter,
制作自定义适配器,
制作一个从主活动接收天气数据的片段,我在主活动中进行天气获取并在适配器中显示该片段...
> java.lang.NullPointerException: 尝试调用虚拟方法
> ‘java.io.Serializable
> android.os.Bundle.getSerializable(java.lang.String)’,它位于空对象
> 引用
> at com.demo.chatbot.WeatherFragment.onCreateView(WeatherFragment.java:25)
weatherList = (ArrayList<Weather>) getArguments().getSerializable("weather"); (WeatherFragment.java:25)
数据获取尚未开始,然后片段尝试加载数据...
主要问题是在获取 API 后我必须设置 weatherAdapter.setWeatherList(weatherList.getWeeklyWeather());
,而这必须在我的主活动中完成,而且在主活动中必须初始化 RecyclerView,但布局应在 MessageAdapter 中完成。
rvWeather = findViewById(R.id.rvWeather);
// rvWeather 应该在 item_chat_bot.xml 中
// 但我必须将其添加到主活动中才能显示
rvWeather.setAdapter(weatherAdapter);
// 否则会出现 No adapter attached; skipping layout
我不明白为什么会这么复杂。在 React Native 中,只需要使用 .map 或 for 循环就可以。我是否忽略了一些明显的事情?
英文:
Want to achieve: a chatbot that returns weather forecast as a RecyclerView inside that chat item (which is in the outer RecyclerView) when the user inputs the word 'weather'.
I want the weather info to be the actual chat item.
I have MessageAdapter and WeatherAdapter which deal with messages and weather forecast info respectively and I have difficulty handling the 'returning weather forecast' case in onBindViewHolder of MessageAdapter.
I have tried many different ways to no avail:
making a ConcatAdapter,
making a custom adapter,
making a fragment that receives the weather data from the main activity where I do the weather fetching and showing that fragment in adapter...
> java.lang.NullPointerException: Attempt to invoke virtual method
> 'java.io.Serializable
> android.os.Bundle.getSerializable(java.lang.String)' on a null object
> reference
> at com.demo.chatbot.WeatherFragment.onCreateView(WeatherFragment.java:25)
weatherList = (ArrayList<Weather>) getArguments().getSerializable("weather"); (WeatherFragment.java:25)
Data fetching hasn't started and then the fragment is trying to load the data...
The main problem is I have to set weatherAdapter.setWeatherList(weatherList.getWeeklyWeather());
after fetching API and this has to be done in my main activity and the RecyclerViews have to be initialized in main activity when the layout should be done in MessageAdapter.
rvWeather = findViewById(R.id.rvWeather);
// rvWeather is supposed to be inside my item_chat_bot.xml
// but I have to add it to main activity for it to show
rvWeather.setAdapter(weatherAdapter);
// otherwise get No adapter attached; skipping layout
I don't understand why it's so complicated. In react native, it's just a matter of using .map or a for loop. Am I missing something obvious?
答案1
得分: 0
以下是翻译好的内容:
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
Message message = messageArrayList.get(position);
switch (message.getType()) {
case "weather":
((WeatherViewHolder) holder).message.setText(message.getMessage());
for (int i = 0; i < weatherList.size(); i++) {
Weather weather = weatherList.get(i);
Glide
.with(context)
.load(context.getResources().getIdentifier(
"icon_" + weather.getWeatherDetails().get(0).getIcon(),
"drawable", context.getPackageName()))
.into(((WeatherViewHolder) holder).mWeatherIcon[i]);
Calendar calendar = new GregorianCalendar();
calendar.setTime(new java.util.Date((long) weather.getDate() * 1000));
((WeatherViewHolder) holder).mDate[i].setText(weekdays[calendar.get(Calendar.DAY_OF_WEEK) % 7]);
((WeatherViewHolder) holder).mMaxTemp[i].setText((int) weather.getTemp().getMax() + "°C");
((WeatherViewHolder) holder).mMinTemp[i].setText((int) weather.getTemp().getMin() + "°C");
((WeatherViewHolder) holder).mWeatherCondition[i].setText(String.valueOf(weather.getWeatherDetails().get(0).getShortDescription()));
}
break;
}
}
public class WeatherViewHolder extends RecyclerView.ViewHolder{
private LinearLayout weatherLayout;
private TextView[] mDate = new TextView[weatherList.size()];
private TextView[] mMaxTemp = new TextView[weatherList.size()];
private TextView[] mMinTemp = new TextView[weatherList.size()];
private TextView[] mWeatherCondition = new TextView[weatherList.size()];
private ImageView[] mWeatherIcon = new ImageView[weatherList.size()];
TextView message;
public WeatherViewHolder(View itemView) {
super(itemView);
message = itemView.findViewById(R.id.message);
weatherLayout = itemView.findViewById(R.id.chat_bot_linear_layout);
for (int i = 0; i < weatherList.size(); i++) {
View view = View.inflate(context, R.layout.item_weather, null);
mWeatherIcon[i] = view.findViewById(R.id.imageViewWeatherIcon);
mDate[i] = view.findViewById(R.id.textViewDate);
mMaxTemp[i] = view.findViewById(R.id.textViewMaxTemp);
mMinTemp[i] = view.findViewById(R.id.textViewMinTemp);
mWeatherCondition[i] = view.findViewById(R.id.textViewWeatherCondition);
weatherLayout.addView(view);
}
}
}
英文:
The point is to have the weather forecast be one message. Use two for loops (one in WeatherViewHolder and one in onBindViewHolder) and TextView arrays in adapter to handle the weather layout. Here are my codes for the adapter:
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
Message message = messageArrayList.get(position);
switch (message.getType()) {
case "weather":
((WeatherViewHolder) holder).message.setText(message.getMessage());
for (int i = 0; i < weatherList.size(); i++) {
Weather weather = weatherList.get(i);
Glide
.with(context)
.load(context.getResources().getIdentifier(
"icon_" + weather.getWeatherDetails().get(0).getIcon(),
"drawable", context.getPackageName()))
.into(((WeatherViewHolder) holder).mWeatherIcon[i]);
Calendar calendar = new GregorianCalendar();
calendar.setTime(new java.util.Date((long) weather.getDate() * 1000));
((WeatherViewHolder) holder).mDate[i].setText(weekdays[calendar.get(Calendar.DAY_OF_WEEK) % 7]);
((WeatherViewHolder) holder).mMaxTemp[i].setText((int) weather.getTemp().getMax() + "°C");
((WeatherViewHolder) holder).mMinTemp[i].setText((int) weather.getTemp().getMin() + "°C");
((WeatherViewHolder) holder).mWeatherCondition[i].setText(String.valueOf(weather.getWeatherDetails().get(0).getShortDescription()));
}
break;
}
}
public class WeatherViewHolder extends RecyclerView.ViewHolder{
private LinearLayout weatherLayout;
private TextView[] mDate = new TextView[weatherList.size()];
private TextView[] mMaxTemp = new TextView[weatherList.size()];
private TextView[] mMinTemp = new TextView[weatherList.size()];
private TextView[] mWeatherCondition = new TextView[weatherList.size()];
private ImageView[] mWeatherIcon = new ImageView[weatherList.size()];
TextView message;
public WeatherViewHolder(View itemView) {
super(itemView);
message = itemView.findViewById(R.id.message);
weatherLayout = itemView.findViewById(R.id.chat_bot_linear_layout);
for (int i = 0; i < weatherList.size(); i++) {
View view = View.inflate(context, R.layout.item_weather, null);
mWeatherIcon[i] = view.findViewById(R.id.imageViewWeatherIcon);
mDate[i] = view.findViewById(R.id.textViewDate);
mMaxTemp[i] = view.findViewById(R.id.textViewMaxTemp);
mMinTemp[i] = view.findViewById(R.id.textViewMinTemp);
mWeatherCondition[i] = view.findViewById(R.id.textViewWeatherCondition);
weatherLayout.addView(view);
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论