java - 我可以直接从 RecyclerView 获取实体房间数据并将其保存到房间数据库吗?

标签 java android android-recyclerview android-room android-database

我有一些适配器,它使用改造来直接从 Web api 获取数据并将其放置到 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 仅当启用网络时才有效

问题是,当通过 Onclick SaveButton 启用网络以创建其他 recyclerview 并在那里设置数据,以便稍后将其脱机时,如何将这些数据从 RecyclerView(或其他方式)设置到我的 Room 数据库。

我正在尝试创建实体

  @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
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();
}

和数据库

  @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;
            }
        }

我需要通过什么方式来创建它?

最佳答案

  1. 创建一个@EntityNotice,这是要存储在 Room DB 中的数据类型。
  2. 创建一个附加到您需要显示此列表的 Activity/Fragment 的 View 模型。
  3. 使用您的 ViewModel 将 API 中的列表存储到您的 Room 数据库中。
  4. 创建一个 LiveData,用于观察数据库并将更新后的列表发送到其他 View 。

在数据库中保存数据的代码。这需要在后台线程上运行。

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 代码

//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

            });

关于java - 我可以直接从 RecyclerView 获取实体房间数据并将其保存到房间数据库吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60248769/

相关文章:

java - 如何将此 ArrayListClass 转换为抽象类

java - PropertySources 中各种源的优先级

android - 我正在从android studio获取以下错误消息

java - 使用 Controller/MVC 初始化 RecyclerView

java - 如何从RecyclerView获取值

java - 将特定项目设置为始终位于 recyclerview 顶部

Java 循环内循环

java - 如何解析txt文件中的2列int

android - 在同一范围内重复使用 Intent 变量是否危险?

android - 如何将评级栏的可编辑属性设置为 false