java – Can i Entity Room data right from RecyclerView and Save it to Room Database?-ThrowExceptions

Exception or error:

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

Im 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 i need to create it?

Please i need advice, i’ll be glad of any kind of help.

How to solve:
  1. Create an @Entity Notice which is your data type to be stored in your Room DB.
  2. Create a View Model which is attached to your Activity/Fragment where you need to show this list.
  3. Use your ViewModel to store the list from API into your Room DB.
  4. 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

            });

Leave a Reply

Your email address will not be published. Required fields are marked *