【问题标题】:ViewModel Problem to show Database changes in M V VM ArchitectureViewModel 问题显示 M V VM 架构中的数据库更改
【发布时间】:2020-07-24 14:08:48
【问题描述】:

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

1-这是我的模型类:

@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 实例在我重新启动应用程序之前不会显示更改。

【问题讨论】:

    标签: java android-room repository-pattern android-viewmodel android-mvvm


    【解决方案1】:

    我终于明白了:

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

    为了解决这个问题,我改变了 ProductViewModel 中的 selectAll 方法如下:

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

    【讨论】:

      【解决方案2】:

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

      LiveData 是一个可观察的数据持有者类。与常规的 observable 不同,LiveData 具有生命周期感知能力,这意味着它尊重其他应用程序组件的生命周期,例如活动、片段或服务。这种意识确保 LiveData 只更新处于活动生命周期状态的应用组件观察者。

      试试这样-

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

      【讨论】:

      • 我没有在我的项目中包含 LiveData 的原因是,在更新数据库后我将关闭当前的 Activity 并且之前的 Activity 只是通过意图通知,所以我不需要让 observable 通知我关于数据库更改
      • 好的,我明白了。但是如果你使用 LiveData,它会在很多方面让事情变得更容易。
      猜你喜欢
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多