房间数据库正在返回 1 个额外的对象
Room database is returning 1 extra object
我有一个创建 3 个用户对象的房间数据库 class -
@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class UserDatabase extends RoomDatabase {
private static UserDatabase instance;
public abstract UserDao userDao();
public static synchronized UserDatabase getInstance(Context context) {
Log.d("inside observe - ", "inside database");
if (instance == null) {
instance = Room.databaseBuilder(context.getApplicationContext(), UserDatabase.class, "user_database").fallbackToDestructiveMigration().addCallback(roomUserCallback).build();
}
return instance;
}
private static RoomDatabase.Callback roomUserCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsyncTask(instance).execute();
}
};
//TODO - delete this in the future. This is just for populating.
private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
static final String URL = "https://www.shortlist.com/media/images/2019/05/40-favourite-songs-of-famous-people-28-1556672663-9rFo-column-width-inline.jpg";
static final String URL2 = "https://img-s-msn-com.akamaized.net/tenant/amp/entityid/BBR9VUw.img?h=416&w=624&m=6&q=60&u=t&o=f&l=f&x=2232&y=979";
static final String URL3 = "https://dz9yg0snnohlc.cloudfront.net/new-what-famous-people-with-depression-have-said-about-the-condition-1.jpg";
private UserDao userDao;
private PopulateDbAsyncTask(UserDatabase db) {
userDao = db.userDao();
}
@Override
protected Void doInBackground(Void... voids) {
userDao.insert(new User(URL, "Barak Obama1", "/@BarakObama1"));
userDao.insert(new User(URL2, "Barak Obama2", "/@BarakObama2"));
userDao.insert(new User(URL3, "Barak Obama3", "/@BarakObama3"));
return null;
}
}
}
我正在使用视图模型来获取用户作为 LiveData。
出于某种原因,在我第一次安装我的应用程序时,我创建了一个额外的 "barak obama1" 用户,并且紧接着所有 3 "normal" 个用户按顺序创建 - barak obama3、2 和 1。
这是我的 MainActivity -
private ArrayList<User> usersList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fetchUserList();
}
private void fetchUserList() {
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
final Observer<List<User>> userObserver = users -> {
Log.d("inside observe - ", "inside main activity, list size - " + users.size());
usersList = (ArrayList) users;
initViewsAndListeners();
addCards();
};
userViewModel.getAllUsers().observe(this, userObserver);
}
private void addCards(){
TinderCardView tinderCardView;
for (int i = 0; i < usersList.size(); i++) {
tinderCardView = new TinderCardView(this);
tinderCardView.bind(usersList.get(i));
Log.d("inside observe - ", "inside main activity, user value - " + usersList.get(i).getUsername());
tinderStackLayout.addCard(tinderCardView);
Log.d("addCardCalled - ", "\nindex value - " + i + "\n" +
"userlist size - " + usersList.size());
}
}
@Override
public void onClick(View view) {
int buttonTag = Integer.valueOf(String.valueOf(view.getTag()));
TinderCardView topCardOnStack = tinderStackLayout.getTopCardOnStack();
topCardOnStack.handleButtonPressed(buttonTag);
// if (buttonTag == 1) { // TODO - move logic to card class
// userViewModel.delete(usersList.get(0));
// //fetchUserList();
// }
}
private void initViewsAndListeners() {
tinderStackLayout = findViewById(R.id.activity_main_tinder_stack_layout);
mDeleteButton = findViewById(R.id.activity_main_delete_button);
mPassButton = findViewById(R.id.activity_main_pass_button);
mApproveButton = findViewById(R.id.activity_main_approve_button);
mDeleteButton.setOnClickListener(this);
mApproveButton.setOnClickListener(this);
mPassButton.setOnClickListener(this);
}
如您所见,我到处都有日志消息,因此您可以理解我现在要向您展示的内容。我得到了一个额外的用户,首先是 "barak obama1" 用户,然后是所有其他 3 -
livedata 发现列表中有 1 个用户,作为卡片添加,然后数据库创建新对象,livedata 调用方法,又添加了 3 个用户。
为什么会这样??如果有人解决了这个问题,我很乐意亲吻他的腿,这不是开玩笑。
编辑 -
这是我的 ViewModel -
public class UserViewModel extends AndroidViewModel {
private UserRepository repository;
private LiveData<List<User>> allUsers;
public UserViewModel(@NonNull Application application) {
super(application);
repository = new UserRepository(application);
allUsers = repository.getAllUsers();
}
public void insert(User user) {
repository.insert(user);
}
public void update(User user) {
repository.update(user);
}
public void delete(User user) {
repository.delete(user);
}
public void deleteAllUsers(){
repository.deleteAllUsers();
}
public LiveData<List<User>> getAllUsers() {
Log.d("inside observe - ", "inside viewmodel");
return allUsers;
}
}
和我的存储库 -
public class UserRepository {
private UserDao userDao;
private LiveData<List<User>> allUsers;
public UserRepository(Application application) {
UserDatabase database = UserDatabase.getInstance(application);
userDao = database.userDao();
allUsers = userDao.getAllUsers();
}
public void insert(User user) {
new InsertUserAsyncTask(userDao).execute(user);
}
public void update(User user) {
new UpdateUserAsyncTask(userDao).execute(user);
}
public void delete(User user) {
new DeleteUserAsyncTask(userDao).execute(user);
}
public void deleteAllUsers() {
new DeleteAllUsersAsyncTask();
}
public LiveData<List<User>> getAllUsers() {
Log.d("inside observe - ", "inside repository");
return allUsers;
}
//TODO - migrate all 4 async tasks into one.
private static class InsertUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
private InsertUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.insert(users[0]);
return null;
}
}
private static class UpdateUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
private UpdateUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.update(users[0]);
return null;
}
}
private static class DeleteUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
private DeleteUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.delete(users[0]);
return null;
}
}
private static class DeleteAllUsersAsyncTask extends AsyncTask<Void, Void, Void> {
private UserDao userDao;
private DeleteAllUsersAsyncTask() {
this.userDao = userDao;
}
@Override
protected Void doInBackground(Void... voids) {
userDao.deleteAllUsers();
return null;
}
}
}
编辑 -
这是我的道 -
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Update
void update(User user);
@Delete
void delete(User user);
@Query("DELETE FROM user_table")
void deleteAllUsers();
@Query("SELECT * FROM user_table ORDER BY id DESC")
LiveData<List<User>> getAllUsers();
}
试着去理解
我发表了评论
这是原始代码,仅供您参考
private ArrayList<User> usersList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.usersList = new ArrayList(); // initalise the array list here
fetchUserList();
}
private void fetchUserList() {
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
final Observer<List<User>> userObserver = users -> {
Log.d("inside observe - ", "inside main activity, list size - " + users.size());
usersList = (ArrayList) users; //dont do this ! instead follow the below instructions
// to do
for(User user : users){
if(!usersList.contains(user)){
usersList.add(user);
}
}
// to do ends here
initViewsAndListeners();
addCards();
};
userViewModel.getAllUsers().observe(this, userObserver);
}
}
看看我做了什么:
- 初始化用户列表
- 并且在观察用户实时数据时我使用循环,在那个循环中我
检查此用户是否已添加
你明白了吗?
在 1 个事务中插入所有用户。
2种方法:
1. 在 dao 中创建一个接收用户列表的函数。
2.在roomDB中创建一个事务(google怎么做。很简单)
我更喜欢第一个
我有一个创建 3 个用户对象的房间数据库 class -
@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class UserDatabase extends RoomDatabase {
private static UserDatabase instance;
public abstract UserDao userDao();
public static synchronized UserDatabase getInstance(Context context) {
Log.d("inside observe - ", "inside database");
if (instance == null) {
instance = Room.databaseBuilder(context.getApplicationContext(), UserDatabase.class, "user_database").fallbackToDestructiveMigration().addCallback(roomUserCallback).build();
}
return instance;
}
private static RoomDatabase.Callback roomUserCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsyncTask(instance).execute();
}
};
//TODO - delete this in the future. This is just for populating.
private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
static final String URL = "https://www.shortlist.com/media/images/2019/05/40-favourite-songs-of-famous-people-28-1556672663-9rFo-column-width-inline.jpg";
static final String URL2 = "https://img-s-msn-com.akamaized.net/tenant/amp/entityid/BBR9VUw.img?h=416&w=624&m=6&q=60&u=t&o=f&l=f&x=2232&y=979";
static final String URL3 = "https://dz9yg0snnohlc.cloudfront.net/new-what-famous-people-with-depression-have-said-about-the-condition-1.jpg";
private UserDao userDao;
private PopulateDbAsyncTask(UserDatabase db) {
userDao = db.userDao();
}
@Override
protected Void doInBackground(Void... voids) {
userDao.insert(new User(URL, "Barak Obama1", "/@BarakObama1"));
userDao.insert(new User(URL2, "Barak Obama2", "/@BarakObama2"));
userDao.insert(new User(URL3, "Barak Obama3", "/@BarakObama3"));
return null;
}
}
}
我正在使用视图模型来获取用户作为 LiveData。 出于某种原因,在我第一次安装我的应用程序时,我创建了一个额外的 "barak obama1" 用户,并且紧接着所有 3 "normal" 个用户按顺序创建 - barak obama3、2 和 1。 这是我的 MainActivity -
private ArrayList<User> usersList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fetchUserList();
}
private void fetchUserList() {
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
final Observer<List<User>> userObserver = users -> {
Log.d("inside observe - ", "inside main activity, list size - " + users.size());
usersList = (ArrayList) users;
initViewsAndListeners();
addCards();
};
userViewModel.getAllUsers().observe(this, userObserver);
}
private void addCards(){
TinderCardView tinderCardView;
for (int i = 0; i < usersList.size(); i++) {
tinderCardView = new TinderCardView(this);
tinderCardView.bind(usersList.get(i));
Log.d("inside observe - ", "inside main activity, user value - " + usersList.get(i).getUsername());
tinderStackLayout.addCard(tinderCardView);
Log.d("addCardCalled - ", "\nindex value - " + i + "\n" +
"userlist size - " + usersList.size());
}
}
@Override
public void onClick(View view) {
int buttonTag = Integer.valueOf(String.valueOf(view.getTag()));
TinderCardView topCardOnStack = tinderStackLayout.getTopCardOnStack();
topCardOnStack.handleButtonPressed(buttonTag);
// if (buttonTag == 1) { // TODO - move logic to card class
// userViewModel.delete(usersList.get(0));
// //fetchUserList();
// }
}
private void initViewsAndListeners() {
tinderStackLayout = findViewById(R.id.activity_main_tinder_stack_layout);
mDeleteButton = findViewById(R.id.activity_main_delete_button);
mPassButton = findViewById(R.id.activity_main_pass_button);
mApproveButton = findViewById(R.id.activity_main_approve_button);
mDeleteButton.setOnClickListener(this);
mApproveButton.setOnClickListener(this);
mPassButton.setOnClickListener(this);
}
如您所见,我到处都有日志消息,因此您可以理解我现在要向您展示的内容。我得到了一个额外的用户,首先是 "barak obama1" 用户,然后是所有其他 3 -
livedata 发现列表中有 1 个用户,作为卡片添加,然后数据库创建新对象,livedata 调用方法,又添加了 3 个用户。
为什么会这样??如果有人解决了这个问题,我很乐意亲吻他的腿,这不是开玩笑。
编辑 -
这是我的 ViewModel -
public class UserViewModel extends AndroidViewModel {
private UserRepository repository;
private LiveData<List<User>> allUsers;
public UserViewModel(@NonNull Application application) {
super(application);
repository = new UserRepository(application);
allUsers = repository.getAllUsers();
}
public void insert(User user) {
repository.insert(user);
}
public void update(User user) {
repository.update(user);
}
public void delete(User user) {
repository.delete(user);
}
public void deleteAllUsers(){
repository.deleteAllUsers();
}
public LiveData<List<User>> getAllUsers() {
Log.d("inside observe - ", "inside viewmodel");
return allUsers;
}
}
和我的存储库 -
public class UserRepository {
private UserDao userDao;
private LiveData<List<User>> allUsers;
public UserRepository(Application application) {
UserDatabase database = UserDatabase.getInstance(application);
userDao = database.userDao();
allUsers = userDao.getAllUsers();
}
public void insert(User user) {
new InsertUserAsyncTask(userDao).execute(user);
}
public void update(User user) {
new UpdateUserAsyncTask(userDao).execute(user);
}
public void delete(User user) {
new DeleteUserAsyncTask(userDao).execute(user);
}
public void deleteAllUsers() {
new DeleteAllUsersAsyncTask();
}
public LiveData<List<User>> getAllUsers() {
Log.d("inside observe - ", "inside repository");
return allUsers;
}
//TODO - migrate all 4 async tasks into one.
private static class InsertUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
private InsertUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.insert(users[0]);
return null;
}
}
private static class UpdateUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
private UpdateUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.update(users[0]);
return null;
}
}
private static class DeleteUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
private DeleteUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.delete(users[0]);
return null;
}
}
private static class DeleteAllUsersAsyncTask extends AsyncTask<Void, Void, Void> {
private UserDao userDao;
private DeleteAllUsersAsyncTask() {
this.userDao = userDao;
}
@Override
protected Void doInBackground(Void... voids) {
userDao.deleteAllUsers();
return null;
}
}
}
编辑 -
这是我的道 -
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Update
void update(User user);
@Delete
void delete(User user);
@Query("DELETE FROM user_table")
void deleteAllUsers();
@Query("SELECT * FROM user_table ORDER BY id DESC")
LiveData<List<User>> getAllUsers();
}
试着去理解 我发表了评论
这是原始代码,仅供您参考
private ArrayList<User> usersList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.usersList = new ArrayList(); // initalise the array list here
fetchUserList();
}
private void fetchUserList() {
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
final Observer<List<User>> userObserver = users -> {
Log.d("inside observe - ", "inside main activity, list size - " + users.size());
usersList = (ArrayList) users; //dont do this ! instead follow the below instructions
// to do
for(User user : users){
if(!usersList.contains(user)){
usersList.add(user);
}
}
// to do ends here
initViewsAndListeners();
addCards();
};
userViewModel.getAllUsers().observe(this, userObserver);
}
}
看看我做了什么:
- 初始化用户列表
- 并且在观察用户实时数据时我使用循环,在那个循环中我 检查此用户是否已添加
你明白了吗?
在 1 个事务中插入所有用户。 2种方法: 1. 在 dao 中创建一个接收用户列表的函数。 2.在roomDB中创建一个事务(google怎么做。很简单)
我更喜欢第一个