I have some adapter which use retrofit to get data right from web api and place it to recyclerview
public class NoticeAdapter extends RecyclerView.Adapter<NoticeAdapter.EmployeeViewHolder> { private Wind wind; private ArrayList<Notice> dataList; private Main main; private Date currentTime = Calendar.getInstance().getTime(); private RecyclerItemClickListener recyclerItemClickListener; public NoticeAdapter(ArrayList<Notice> dataList, Main main, Wind wind, RecyclerItemClickListener recyclerItemClickListener) { this.dataList = dataList; this.main = main; this.wind = wind; this.recyclerItemClickListener = recyclerItemClickListener; } @Override public EmployeeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); View view = layoutInflater.inflate(R.layout.single_view_row, parent, false); return new EmployeeViewHolder(view); } @Override public void onBindViewHolder(EmployeeViewHolder holder, @SuppressLint("RecyclerView") final int position) { if(getAddressMap()!=null){holder.txtNoticeAddress.setText("Loc: "+getAddressMap());}else{holder.txtNoticeAddress.setText("Loc: Unknown location");} holder.imageIcon.setImageURI(Uri.parse("android.resource://com.locweather/drawable/i"+dataList.get(position).getIcon())); holder.txtNoticeWind.setText("Wind: "+roundUp(+wind.getSpeed(),1)+"m/s, "+arrow()); holder.txtNoticeTempMain.setText(roundUp(+main.getTemp(),1)+"°C"); holder.txtNoticeWeather.setText(dataList.get(position).getWeather()+" : "+dataList.get(position).getInfo()); holder.txtNoticeTemp.setText("Feels: "+roundUp(+main.getFeelsLike(),1)+"°C "); holder.txtNoticeTime.setText(currentTime.toString()); holder.txtNoticeHumidity.setText("Humidity: "+main.getHumidity()+"%"); holder.txtNoticePressure.setText("Pressure: "+main.getPressure()+"hPa"); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { recyclerItemClickListener.onItemClick(dataList.get(position)); } }); } @Override public int getItemCount() { return dataList.size(); } class EmployeeViewHolder extends RecyclerView.ViewHolder { ImageView imageIcon; TextView txtNoticeWeather, txtNoticeTempMain,txtNoticeTemp, txtNoticeHumidity,txtNoticeAddress,txtNoticePressure,txtNoticeWind,txtNoticeTime; EmployeeViewHolder(View itemView) { super(itemView); imageIcon=itemView.findViewById(R.id.image_icon); txtNoticeTime= itemView.findViewById(R.id.txt_time); txtNoticeWind= itemView.findViewById(R.id.txt_notice_wind); txtNoticeAddress= itemView.findViewById(R.id.txt_notice_title); txtNoticeWeather = itemView.findViewById(R.id.txt_notice_weather); txtNoticeTemp = itemView.findViewById(R.id.txt_notice_temp); txtNoticeHumidity = itemView.findViewById(R.id.txt_notice_humidity); txtNoticePressure = itemView.findViewById(R.id.txt_notice_pressure); txtNoticeTempMain = itemView.findViewById(R.id.txt_notice_temp_main); } }
This is my recyclerview This works only when network is enabled
The question is how to set this data right from RecyclerView (or other way) to my Room DataBase when network is enabled by Onclick SaveButton to create other recyclerview and set data there, to get it offline later.
I’m trying to create Entity
@Entity public class WeatherData { @PrimaryKey(autoGenerate = true) private long id; private String address; private Double windSpeed; private Integer windDegree; private String datalistIcon; private String datalistInfo; private String datalistWeather; private Double mainTemp; private Double mainFeel; private Integer mainHumidity; private Integer mainPressure; private String time; private Double locLat; private Double locLon; public WeatherData(){} @Ignore public WeatherData(String address, Double windSpeed, Integer windDegree, String datalistIcon,String datalistInfo,String datalistWeather, Double mainTemp,Double mainFeel,Integer mainHumidity,Integer mainPressure,String time,LatLng currentLocation,Double locLat,Double locLon) { this.address = address; this.windSpeed = windSpeed; this.windDegree = windDegree; this.datalistIcon=datalistIcon; this.datalistInfo=datalistInfo; this.datalistWeather=datalistWeather; this.mainTemp=mainTemp; this.mainFeel=mainFeel; this.mainHumidity=mainHumidity; this.mainPressure=mainPressure; this.time=time; this.locLat=locLat; this.locLon=locLon; }
Dao
@Dao public interface WeatherDataDao { @Insert(onConflict = OnConflictStrategy.REPLACE) void saveAll(List<WeatherData> weathers); @Insert(onConflict = OnConflictStrategy.REPLACE) void save(WeatherData weather); @Update void update(WeatherData weather); @Delete void delete(WeatherData weather); @Query("SELECT * FROM WeatherData") LiveData<List<WeatherData>> findAll(); }
and DataBase
@Database(entities = {WeatherData.class}, version = 1) public abstract class WeatherDatabase extends RoomDatabase { public static WeatherDatabase INSTANCE; public abstract WeatherDataDao weatherDao(); private static final Object sLock = new Object(); public static WeatherDatabase getInstance(Context context) { synchronized (sLock) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), WeatherDatabase.class, "Weathers.db") .allowMainThreadQueries() .build(); } return INSTANCE; } }
Which way do I need to create it?
Advertisement
Answer
- Create an
@Entity Notice
which is your data type to be stored in your Room DB. - Create a View Model which is attached to your Activity/Fragment where you need to show this list.
- Use your ViewModel to store the list from API into your Room DB.
- Create a LiveData which observes on the DB and sends the updated list to the other view.
Code for Saving Data in DB. This needs to be run on Background Thread.
public static void saveNoticeList(Context context, List<Notice> noticeList) { if (context != null && noticeList != null) { RoomDatabaseCreator.getInstance(context) .getDatabase() .noticeDao() .saveNotices(noticeList); } } // For Saving in background you can use RxJava, I am using a new thread for simplification backgroundHandler.post(() -> { saveNoticeList(getActivity(), dataList); });
ViewModel
public class NoticeViewModel extends AndroidViewModel { public MutableLiveData<List<Notice>> mNoticesLiveData = new MutableLiveData<>(); private Context mContext; public NoticeViewModel(final Application application) { super(application); mContext = application.getApplicationContext(); mNoticesLiveData = Transformations.switchMap(databaseCreated, (Function<Boolean, LiveData<List<Notice>>) isDbCreated -> { if (!Boolean.TRUE.equals(isDbCreated)) { // Not needed here, but watch out for null //noinspection unchecked return ABSENT; } else { return databaseCreator.getDatabase() .noticedao() .getSavedNotices(); } } }); public LiveData<List<Notice> getNoticeLiveData() { return mNoticesLiveData; } }
Activity Code where you need to show the saved data
//1. Initialize the viewModel NoticeViewModel viewModel = ViewModelProviders.of(this).get(NoticeViewModel.class); //2. Subscribe to the saved notices live-data to get updates in your view viewModel.getNoticeLiveData().observe(this list -> { if (list.isEmpty()) { return; } // Add the list in your adapter });