1

I need when refresh page make request to API and insert getting data to my room database. But when I try to insert data I get io.reactivex.exceptions.OnErrorNotImplementedException: UNIQUE constraint failed: data.id (code 1555). So I decided to check is my table empty and if isn't make update request, but so my recyclerview doesn't work normally, and data doesn't update properly on db. Here is my code:

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

And onCreate method:

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

Please help me

ankuranurag2
  • 2,300
  • 15
  • 30
anna
  • 433
  • 7
  • 18
  • You are trying to insert an object that already exists. If you want to update it, you should set proper [OnConflictStrategy](https://developer.android.com/reference/android/arch/persistence/room/OnConflictStrategy). – EpicPandaForce Feb 16 '19 at 20:51

2 Answers2

1

If you want an insert operation to overwrite existing object in DB, then you should use OnConflictStrategy.REPLACE.

See example:

@Dao
interface CatDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertCats(cats: List<Cat>)
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
-1

You have to check you List<Data> one by one in your updateData For exemple :

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

                       }
                   }
                }  
            }
        }

you can create a new method in your DataDao findDataById(string id) and use it the boolean isStored(String id) method and update it directly

Good luck ! hope that will help you.

RaffMag
  • 114
  • 5
  • thank you for your answer, but recyclerview still doesn't work normally, when I try to scroll my recyclerview begin to shake and doesn't show all items. – anna Feb 15 '19 at 12:11