【问题标题】:How to update room database based on server response如何根据服务器响应更新房间数据库
【发布时间】:2019-07-26 19:07:11
【问题描述】:

我正在从服务器获取数据并保存在房间数据库中,然后从房间中将其显示在回收站视图中。数据完美地保存在房间数据库中并显示在回收站视图中。

问题:当我从服务器数据库中删除一些数据时,之前保存的旧副本仍然存在于房间中。

我想要什么:我不想在回收站视图中显示从服务器删除的数据。那么如何根据服务器响应更新房间数据库。

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

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 {

@NonNull
@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 id = list.get(i).getId();
                                      String names = list.get(i).getName();
                                      String age = list.get(i).getAge();

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

MainActivity.java

public class MainActivity extends AppCompatActivity {

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

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

    prg = findViewById(R.id.prg);

    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) {

            prg.setVisibility(View.INVISIBLE);
            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();
}

请让我知道如何获得所需的结果。任何帮助将不胜感激。

谢谢

【问题讨论】:

    标签: android retrofit2 android-room


    【解决方案1】:

    使用getRoomUsers()onResponse() 的存储库中获取已知用户列表。

    对于response.body()中的每个用户,检查其在已知用户列表中是否有对应的列表项。删除此项。

    之后,已知用户列表将仅包含已从服务器中删除的用户。因此,对于这些剩余用户中的每一个,您都可以将其从房间数据库中删除。

    下面的代码 sn -p 显示了如何找到服务器当前不知道的用户:

    if (response.body() != null) {
    
        List<User> list = response.body();
        List<User> previouslyKnownUsers = new ArrayList<>(userDb.userDao().getRoomUsers().getValue());
    
        for (int i = 0; i < list.size(); i++) {
            String id = list.get(i).getId();
            String names = list.get(i).getName();
            String age = list.get(i).getAge();
    
            User user = new User(id, names, age);
    
            userDb.userDao().Insert(user);
    
            User knownUser = null; 
            for(User previouslyKnownUser: previouslyKnownUsers){
                if(previouslyKnownUser.getId().equals(user.getId())){
                    knownUser = previouslyKnownUser;
                    break;
                }
            }
            if(knownUser != null){
                previouslyKnownUsers.remove(knownUser);
            }
        }
    
        for(User currentlyUnknownUser: previouslyKnownUsers){
            userDb.userDao().Delete(currentlyUnknownUser);
        }
    }
    

    为了让它工作,你必须在UserDao.java 中添加一个方法Delete(User user)

    【讨论】:

    • 我如何在代码中实现这一点,请您发布一些代码。
    • @Digvijay - 明天会做(这里有点晚了)一个问题:如果两个用户具有相同的 ID,他们是否相等(不是在 Java 中,而是在现实世界中)?
    • @Digvijay - 添加了代码 sn-p。我假设两个用户实例引用相同的“真实”用户,如果它们具有相同的 id
    • 当我尝试实施您的解决方案时。这里List&lt;User&gt; previouslyKnownUsers = new ArrayList&lt;&gt;(userDb.userDao().getRoomUsers().getValue()); 说的是Attempt to invoke interface method java.lang.objec[] java.util.Collection.toArray[] on a null object reference.
    • @Digvijay - 这听起来好像 getRoomUsers() 方法内部的某些东西“不起作用”。抱歉,由于无法访问您的完整代码,因此我不知道如何为您提供帮助。如果一切正常,我只能向您展示如何处理 getRoomUsers() 返回的列表
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 2020-12-10
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多