Viewmodel 不会更新 Android Room 中的数据,但会成功插入其中

Viewmodel doesn't update data from Android Room, but successfully insert in it

提问人:AShX 提问时间:2/1/2021 更新时间:2/1/2021 访问量:923

问:

我试图通过这门课程来理解 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 后回收器视图不显示数据,理论上应该处理它。如果需要,我将提供额外的代码。提前致谢。

java android mvvm android-recycler查看 android-room

评论


答:

3赞 a_local_nobody 2/1/2021 #1
public void setListContent(List <Dashboard_Account> pad_list) {
    this.pad_list = pad_list;
    notifyItemChanged(getItemCount());
}

可能是错的,但我真的看不出在这里这样做的意义,请尝试添加notifyItemChangednotifyDataSetChanged()


notifyItemChanged告诉回收商特定项目已被更改,同时通知回收商所有数据(可能)已更改,这会强制回收商重新绑定其拥有的所有项目。notifyDataSetChanged

从你提到的课程来看,没有参考,所以我不确定你为什么把它加:)notifyItemChanged

您提供的课程链接包含:

void setWords(List<Word> words){
       mWords = words;
       notifyDataSetChanged(); <-- notifyDataSetChanged, not itemChanged
   }
3赞 Zain 2/1/2021 #2

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