我正在使用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);
}
}
}
有人请告诉我如何才能达到预期的结果。任何帮助都将不胜感激。
谢谢
答案很简单,您没有唯一的主键。您正在使用
字符串id=UUID.随机UUID(). toString();
在您的第一个请求中,您可能有以下内容:
用户("mdkasdkasjkdjakjdkasd","Zun",22);
在你的第二个请求中,你会得到
用户("djei3ujf493j9fj49dj9","Zun",22);
因此,您的数据库中总是会有重复的条目,因为room认为名为“Zun”的用户不相同。
为了解决这个问题,请创建一个对User
类唯一的唯一主键。不要使用随机文本生成器。
好吧你应该这样做,
@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