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?
Advertisement
Answer
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); } } }