【问题标题】:Data is not updated normally (room database)数据未正常更新(房间数据库)
【发布时间】:2019-02-15 10:56:46
【问题描述】:

我需要在刷新页面时向API 发出请求并将获取数据插入我的房间数据库。但是当我尝试插入数据时,我得到io.reactivex.exceptions.OnErrorNotImplementedException: UNIQUE constraint failed: data.id (code 1555). 所以我决定检查我的表是否为空,如果没有发出更新请求,但是我的recyclerview 无法正常工作,并且数据库上的数据无法正确更新。这是我的代码:

 private void getData() {
        progressBar.setVisibility(View.VISIBLE);
        APIInterface service = RetrofitInstance.getRetrofitInstance().create(APIInterface.class);
        Call<DataAll> call = service.getData();
        call.enqueue(new Callback<DataAll>() {
            @Override
            public void onResponse(Call<DataAll> call, Response<DataAll> response) {
                if(response.body() != null) {
                     List<Data> allData = response.body().getData();

                    Disposable disposable = db.dataDao().dataSize().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Integer>() {
                        @Override
                        public void accept(Integer dbSize) throws Exception {
                            if(dbSize > 0)
                                updateData(allData);
                            else
                                insertData(allData);
                            fillListFromDb();

                        }
                    });
                }
            }

            @Override
            public void onFailure(Call<DataAll> call, Throwable t) {
                tvErrorMessage.setVisibility(View.VISIBLE);
                recyclerDataList.setVisibility(View.GONE);
                progressBar.setVisibility(View.GONE);
                swipeRefreshToUpdateList.setRefreshing(false);
                Toast.makeText(getApplicationContext(), R.string.errorMessage, Toast.LENGTH_LONG).show();
                t.printStackTrace();
            }
        });
    }

    private void fillListFromDb() {
            Disposable disposable = db.dataDao().getAllData().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<List<Data>>() {
            @Override
            public void accept(List<Data> data) throws Exception {
                listData.clear();
                listData.addAll(data);
                adapter = new MyAdapter(listData);
                adapter.notifyDataSetChanged();
                recyclerDataList.setAdapter(adapter);
                progressBar.setVisibility(View.GONE);
                swipeRefreshToUpdateList.setRefreshing(false);
            }
        });
    }

    private void updateData(List<Data> data) {
        Completable.fromAction( () ->
                db.dataDao().updateData(data))
                .subscribeOn(Schedulers.io())
                .subscribe();
    }

    private void insertData(List<Data> data) {
        Completable.fromAction(() ->
            db.dataDao().addData(data)).
                subscribeOn(Schedulers.io())
                .subscribe();
    }

onCreate方法:

   @Override
        protected void onCreate(Bundle savedInstanceState) {
  //  ……
      swipeRefreshToUpdateList.setOnRefreshListener(() -> {
                    tvErrorMessage.setVisibility(View.GONE);
                    recyclerDataList.setVisibility(View.VISIBLE);
                    getData();
                });
    }

请帮帮我

【问题讨论】:

  • 您正试图插入一个已经存在的对象。如果你想更新它,你应该设置正确的OnConflictStrategy

标签: android rx-java2 android-room android-database android-jetpack


【解决方案1】:

如果您希望insert 操作覆盖数据库中的现有对象,则应使用OnConflictStrategy.REPLACE

查看示例:

@Dao
interface CatDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertCats(cats: List<Cat>)

【讨论】:

    【解决方案2】:

    您必须在updateData 中一一检查您的List&lt;Data&gt; 例如:

    @Override
            public void onResponse(Call<DataAll> call, Response<DataAll> response) {
                if(response.body() != null) {
                     List<Data> allData = response.body().getData();
                     for (Data data:allData){
                      if(isStored(data.getId())){
                          updateData(data);
                            else {
                            insertData(data);
                            }
    
                           }
                       }
                    }  
                }
            }
    

    您可以在DataDao findDataById(string id) 中创建一个新方法并使用boolean isStored(String id) 方法并直接更新它

    祝你好运!希望对您有所帮助。

    【讨论】:

    • 感谢您的回答,但是当我尝试滚动时,recyclerview 仍然无法正常工作,我的 recyclerview 开始抖动并且不显示所有项目。
    猜你喜欢
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-09
    • 2020-04-14
    相关资源
    最近更新 更多