提问人:AShX 提问时间:2/1/2021 更新时间:2/1/2021 访问量:923
Viewmodel 不会更新 Android Room 中的数据,但会成功插入其中
Viewmodel doesn't update data from Android Room, but successfully insert in it
问:
我试图通过这门课程来理解 Room 持久性库,但是,我坚持更新 RecyclerView 并在 Room 中填充数据。对不起,这个样板代码。
数据成功传递到 Room 并保留在那里,因为 Android 数据库检查器向我显示,但与此同时,Rycyclerview 是空的。这是我的代码: 项目:
@Entity (tableName = "active_accounts")
public class Dashboard_Account {
@PrimaryKey (autoGenerate = true)
int accountID;
@ColumnInfo(name = "accountName")
String accountName;
@ColumnInfo(name = "accountEmail")
String accountEmail;
public Dashboard_Account() {
}
public Dashboard_Account(String accountName,String accountEmail) {
this.accountName = accountName;
this. accountEmail = accountEmail;
}
//getters and setters
道
@Dao
public interface Dashboard_DAO {
@Insert (onConflict = OnConflictStrategy.REPLACE)
void insert(Dashboard_Account... dashboard_accounts);
@Delete
void delete(Dashboard_Account account);
@Query("DELETE FROM active_accounts")
void deleteAll();
@Update
void update(Dashboard_Account account);
@Query("SELECT * FROM active_accounts" )
LiveData<List<Dashboard_Account>> getAllAccounts();
}
数据库
@Database(entities = {Dashboard_Account.class},version = 2,exportSchema = false)
public abstract class Dashboard_Database extends RoomDatabase {
public abstract Dashboard_DAO dashboard_dao();
private static Dashboard_Database INSTANCE;
public static Dashboard_Database getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (Dashboard_Database.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
Dashboard_Database.class, "account_database")
.fallbackToDestructiveMigration()
.build();
}
}
}
return INSTANCE;
}
}
存储库类
public class Dashboard_Repository {
private Dashboard_DAO mDashboardDao;
private LiveData<List<Dashboard_Account>> mAllAccounts;
Dashboard_Repository(Application application) {
Dashboard_Database db = Dashboard_Database.getDatabase(application);
mDashboardDao = db.dashboard_dao();
mAllAccounts = mDashboardDao.getAllAccounts();
}
LiveData<List<Dashboard_Account>> getAllAcounts(){
return mAllAccounts;
}
public void insert (Dashboard_Account account) {
new insertAsyncTask(mDashboardDao).execute(account);
}
private static class insertAsyncTask extends AsyncTask<Dashboard_Account, Void, Void> {
private Dashboard_DAO mAsyncTaskDao;
insertAsyncTask(Dashboard_DAO mDashboardDao) {
mAsyncTaskDao = mDashboardDao;
}
@Override
protected Void doInBackground(final Dashboard_Account... params) {
mAsyncTaskDao.insert(params[0]);
return null;
}
}
视图模型
public class Dashboard_ViewModel extends AndroidViewModel {
private Dashboard_Repository mRepo;
private LiveData<List<Dashboard_Account>> mAllAccounts;
public Dashboard_ViewModel(@NonNull Application application) {
super(application);
mRepo = new Dashboard_Repository(application);
mAllAccounts = mRepo.getAllAcounts();
}
LiveData<List<Dashboard_Account>> getmAllAccounts() { return mAllAccounts; }
public void insert(Dashboard_Account account) { mRepo.insert(account); }
}
为了添加数据,我将 DialogFragment 与放置在 Fragment onViewCreated() 中的 setFragmentResultListener 一起使用
public class Dashboard_Fragment extends Fragment {
…
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
setRecyclerView();
getParentFragmentManager().setFragmentResultListener("fragmentKey", getViewLifecycleOwner(), (requestKey, result) -> {
String name = result.getString("nameResult");
String email = result.getString ("email");
Dashboard_Account account = new Dashboard_Account(name,email);
dashboardViewModel.insert(account);
});
}
以及 recyclerview 设置的代码:
private void setRecyclerView(){
binding.accountView.setLayoutManager(new LinearLayoutManager(requireContext()));
adapter = new Dashboard_RecyclevrViewAdapter(AccountItemList);
dashboardViewModel.getmAllAccounts().observe(requireActivity(), accounts -> {
adapter.setListContent(AccountItemList);
});
binding.accountView.setAdapter(adapter);
}
RecyclerViewAdapter 是典型的,这里是 BindViewHolder 和 setListcontent:
public class Dashboard_RecyclevrViewAdapter extends RecyclerView.Adapter<Dashboard_RecyclevrViewAdapter.MyViewHolder> {
....
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
if(pad_list!=null){
final Dashboard_Account account = pad_list.get(position);
holder.binding.accountType.setText(account.getAccountName());
holder.binding.acountemail.setText(account.getAccountValue()));
}
}
…
public void setListContent(List <Dashboard_Account> pad_list) {
this.pad_list = pad_list;
notifyItemChanged(getItemCount());
}
….
}
我真的不明白为什么在我将项目添加到 ViewModel 后回收器视图不显示数据,理论上应该处理它。如果需要,我将提供额外的代码。提前致谢。
答:
public void setListContent(List <Dashboard_Account> pad_list) {
this.pad_list = pad_list;
notifyItemChanged(getItemCount());
}
可能是错的,但我真的看不出在这里这样做的意义,请尝试添加notifyItemChanged
notifyDataSetChanged()
notifyItemChanged
告诉回收商特定项目已被更改,同时通知回收商所有数据(可能)已更改,这会强制回收商重新绑定其拥有的所有项目。notifyDataSetChanged
从你提到的课程来看,没有参考,所以我不确定你为什么把它加:)notifyItemChanged
您提供的课程链接包含:
void setWords(List<Word> words){
mWords = words;
notifyDataSetChanged(); <-- notifyDataSetChanged, not itemChanged
}
除了@a_local_nobody指出的这一点之外,您还需要将更新的列表发送到适配器,而不是原始列表notifyDataSetChanged()
RecyclerView
为此,请替换为dapter.setListContent(AccountItemList);
dapter.setListContent(accounts);
setRecyclerView()
private void setRecyclerView(){
binding.accountView.setLayoutManager(new LinearLayoutManager(requireContext()));
adapter = new Dashboard_RecyclevrViewAdapter(AccountItemList);
dashboardViewModel.getmAllAccounts().observe(requireActivity(), accounts -> {
adapter.setListContent(accounts); // <<< Change here
});
binding.accountView.setAdapter(adapter);
}
评论