显示 M V VM 架构中的数据库更改的 ViewModel 问题

ViewModel Problem to show Database changes in M V VM Architecture

在我尝试接近 M V VM 架构时,我做了这个简单的例子,我的问题是 viewModel 不显示我对数据库所做的更改,直到我重新启动我的应用程序。

1-这是我的模型class:

@Entity
public class Product {
    @ColumnInfo
    @PrimaryKey(autoGenerate = true)
    private int id;

    @ColumnInfo
    private String productTitle;

    public Product(String productTitle) {this.productTitle = productTitle;}

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getProductTitle() { return productTitle; }
    public void setProductTitle(String productTitle) { this.productTitle = productTitle; }
}

2-这是 DAO

@Dao
public interface ProductDao {
    @Insert   void insert(Product product);
    @Update   void update(Product product);
    @Delete   void delete(Product product);
    @Query("select * from Product")
    List<Product> selectAll();
}

3- 这是我的 AppDatabase:

@Database(entities = { Product.class},version = 1)
public abstract class AppDatabase extends RoomDatabase {

    private static final String DATABASE_NAME = "productDB";
    private static AppDatabase instance;
    public abstract ProductDao getProductDao();

    public static AppDatabase getInstance(Context context){
        if (instance == null) {
            instance = Room.databaseBuilder(context,AppDatabase.class,DATABASE_NAME)
                           .allowMainThreadQueries()
                           .build();}
        return instance;
    }
}

4-这是存储库:

public class ProductRepository {
    private ProductDao productDao;
    private List<Product> productList;

    public ProductRepository(Application application) {
        productDao = AppDatabase.getInstance(application).getProductDao();
        productList = productDao.selectAll();
    }
    public void insert (Product myProduct) { productDao.insert(myProduct);}
    public void delete (Product product)   { productDao.delete(product);}
    public void update (Product product)   { productDao.update(product);}
    public List<Product> selectAll()       { return productList;}
}

5-这是 ViewModel:

    public ProductViewModel(@NonNull Application application) {
        super(application);
       repository = new ProductRepository(application);
       productList = repository.selectAll();
    }
    public void insert(Product product)  {  repository.insert(product);  }
    public void delete (Product product) {  repository.delete(product);}
    public void update(Product product)  {  repository.update(product);}
    public List<Product> selectAll()     {  return productList;    }
}

最后这是我在主程序中使用它的方式 Activity:

.
.
public void btnInsertOnclick(View view) {
        ProductViewModel productViewModel = new ViewModelProvider(this).get(ProductViewModel.class);

        productViewModel.insert(new Product(" product" +String.valueOf(new Random().nextInt(100))  ));

        //-----------> testDB();
        List<Product> testList = productViewModel.selectAll();

        for (Product item : testList) {
            Log.e("dataBaseTest", "CAR #" + item.getId() + " " + item.getProductTitle() + " " );}
    }
.
.

如果我使用存储库实例而不是 viewModel 来制作上面的日志,我可以看到对数据库进行了更改,但是 viewModel 实例在我重新启动我的应用程序之前不会显示更改。

终于明白了:

使用“provider”方法创建 ViewModel 将生成一个“单例”实例。因此,在下一个 ProductViewModel 实例制作中,我将使用旧的,当我在构造函数中填写产品列表时,我将获得旧数据。

为了解决问题,我更改了 ProductViewModel 中的 selectAll 方法,如下所示:

 public List<Product> selectAll()     {  return repository.selectAll();    }

我只是好奇,你为什么不在你的案例中使用 LiveData。每当您的数据库中与列表相关的更改时,LiveData 会自动通知您。

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

这样试试-

[1]像下面这样将所有列表放入 LiveData Holder

LiveData<List<Product>>

[2] 在 onCreate 中创建一个 ViewMoel 实例并观察 LiveData 变量

productViewModel = new ViewModelProvider(this).get(ProductViewModel.class);
productViewModel.selectAll().observe(getViewLifecycleOwner(), new Observer<List<Product>>() {
        @Override
        public void onChanged(List<Product> testList) {
            for (Product item : testList) {
                Log.d("dataBaseTest", "CAR #" + item.getId() + " " + item.getProductTitle() + "   size : " + testList.size());
            }
        }
    });

[3] 那么你只需要在 clicklistner 中插入你的数据。

    private void performAction() {
        productViewModel.insert(new Product(" product" +String.valueOf(new Random().nextInt(100))  ));
    }