提问者:小点点

使用改造2获取数据并保存在房间中


我正在使用RetreFit2从服务器获取数据,并在房间数据库中获取保存数据,然后在回收器视图中显示。每当应用程序运行时,它会从服务器获取数据并将其保存在房间数据库中。我已成功从服务器获取JSON数据并保存在房间数据库中,并从房间中正确显示在回收器视图中。

问题:每当从服务器获取数据时,它都会再次在房间中插入相同的旧数据,因为相同的数据在回收器视图中显示多次。

我想要的:我不想让回收器视图多次显示相同的数据。我不想在房间数据库中再次复制相同的数据。

这是我到目前为止所做的:

UserDao.java

@Dao
public interface UserDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
void Insert(User... users);

@Query("SELECT * FROM Users")
LiveData<List<User>> getRoomUsers();

}

User.java

@Entity(tableName = "Users")
public class User {

@PrimaryKey
private String id;

@ColumnInfo(name = "name")
@SerializedName("name")
@Expose
private String name;

@ColumnInfo(name = "age")
@SerializedName("age")
@Expose
private String age;

public User(String id,String name, String age) {
this.id = id; 
this.name = name;
this.age = age;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}
}    

UserRepository.java

public class UserRepository {

private Context context;
private UserDb userDb;
private LiveData<List<User>> listLiveData;

public UserRepository(Context context) {
this.context = context;
userDb = UserDb.getInstance(context);
listLiveData = userDb.userDao().getRoomUsers();
}

public void getUserList(){

      Retrofit retrofit = RetrofitClient.getInstance();
      ApiService apiService = retrofit.create(ApiService.class);

      Call<List<User>> userList = apiService.getUser();

      userList.enqueue(new Callback<List<User>>() {
          @Override
          public void onResponse(Call<List<User>> call, final Response<List<User>> response) {

              Completable.fromAction(new Action() {
                      @Override
                      public void run() throws Exception {

                          if(response.body() != null) {

                              List<User> list = response.body();

                              for (int i = 0; i < list.size(); i++) {

                                  String names = list.get(i).getName();
                                  String age = list.get(i).getAge();
                                  String id = UUID.randomUUID().toString();


                                  User user = new User(id,names,age);

                                  userDb.userDao().Insert(user);
                              }

                          }

                      }
                  }).subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new CompletableObserver() {
                        @Override
                        public void onSubscribe(Disposable d) {

                        }

                        @Override
                        public void onComplete() {

                            Toast.makeText(context,"Data inserted",Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onError(Throwable e) {

                            Toast.makeText(context,e.getMessage(),Toast.LENGTH_SHORT).show();
                        }
                    });


          }

          @Override
          public void onFailure(Call<List<User>> call, Throwable t) {
              Toast.makeText(context,t.getMessage(),Toast.LENGTH_LONG).show();
          }
      });

}

public LiveData<List<User>> getRoomUsers(){

    return listLiveData;
  }
}

UserViewModel.java

public class UserViewModel extends AndroidViewModel {

private UserRepository repo;
private LiveData<List<User>> listLiveData;

public UserViewModel(@NonNull Application application) {
super(application);

repo = new UserRepository(application);
listLiveData = repo.getRoomUsers();

}

public LiveData<List<User>> getListLiveData() {
return listLiveData;
}
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

UserRepository userRepository;
RecyclerView recyclerView;
UserViewModel userModel;
List<User> userList;
UserAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

userRepository = new UserRepository(this);
userModel = ViewModelProviders.of(this).get(UserViewModel.class);

recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

userList = new ArrayList<>();

adapter = new UserAdapter(userList,this);
recyclerView.setAdapter(adapter);

userModel.getListLiveData().observe(this, new Observer<List<User>>() {

    @Override
    public void onChanged(List<User> users) {
        adapter.setUserList(users);
    }
});

FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent i = new Intent(MainActivity.this,AddUser.class);
        startActivity(i);
    }
});

    userRepository.getUserList();
}

UserAdapter.java

public class UserAdapter extends 
RecyclerView.Adapter<UserAdapter.ViewHolder> {

List<User> userList;
Context context;

public UserAdapter(List<User> userList, Context context) {
    this.userList = userList;
    this.context = context;
}

@NonNull
@Override
public UserAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_row_layout,parent,false);

    ViewHolder viewHolder = new ViewHolder(v);

    return viewHolder;
}

@Override
public void onBindViewHolder(@NonNull UserAdapter.ViewHolder holder, int position) {

    User users = userList.get(position);

    holder.row_name.setText(users.getName());
    holder.row_age.setText(users.getAge());
}

@Override
public int getItemCount() {
    return userList.size();
}

public void setUserList(List<User> userList) {
    this.userList = userList;
    notifyDataSetChanged();
}

public class ViewHolder extends RecyclerView.ViewHolder {

    TextView row_name,row_age;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);

        row_name = itemView.findViewById(R.id.row_name);
        row_age = itemView.findViewById(R.id.row_age);
    }
  }
}

有人请告诉我如何才能达到预期的结果。任何帮助都将不胜感激。

谢谢


共2个答案

匿名用户

答案很简单,您没有唯一的主键。您正在使用

字符串id=UUID.随机UUID(). toString();

在您的第一个请求中,您可能有以下内容:

用户("mdkasdkasjkdjakjdkasd","Zun",22);

在你的第二个请求中,你会得到

用户("djei3ujf493j9fj49dj9","Zun",22);

因此,您的数据库中总是会有重复的条目,因为room认为名为“Zun”的用户不相同。

为了解决这个问题,请创建一个对User类唯一的唯一主键。不要使用随机文本生成器。

匿名用户

好吧你应该这样做,

  1. 检查用户是否存在于db中,
@Query("SELECT * FROM user WHERE id = :userId")
public User idUserExists(int userId);
@Update
public void updateUser(User user); // keep the model with same user id
@Insert 
public void insertUser(User user); // Model with new user Id