无法观察空数据 - 带有 Livedata 的 MVVM
Cannot observe null data - MVVM with Livedata
我使用 MVVM 模式和 LiveData 创建了简单的应用程序来观察数据。我显示的列表显示在片段中。对我来说,一切似乎都很好,因为我将我的代码与其他有效的示例进行了比较,但没有发现任何错误。
当 activity 启动时,我交换片段并在 onActivityCreated
行 mViewModel.getAllShops().observe(this, new Observer<List<Shop>>() { //<--error
中出现以下错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference
我的架构是:
- 实体 - Shop.class
- 道 - ShopDao.class
- 资料库 - ShopRepository.class
- ViewModel - ShopListViewModel
- 在 RecyclerView 中显示数据的片段 - ShopList.java
Shop.class:
@Entity(tableName = "shops")
public class Shop {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
public int id;
@ColumnInfo(name = "shop_name")
public String shopName;
@ColumnInfo(name = "shop_description")
public String shopDescription;
@ColumnInfo(name = "radius")
public int radius;
@ColumnInfo(name = "latitude")
public String latitude;
@ColumnInfo(name = "longitude")
public String longitude;
@ColumnInfo(name = "isFavourite")
public int isFavouriteShop;
public int getId() {
return id;
}
public String getShopName() {
return shopName;
}
public String getShopDescription() {
return shopDescription;
}
public int getRadius() {
return radius;
}
public String getLatitude() {
return latitude;
}
public String getLongitude() {
return longitude;
}
public int getIsFavouriteShop() {
return isFavouriteShop;
}
@Ignore
public Shop(String shopName, String shopDescription, int radius, String latitude, String longitude, int isFavouriteShop) {
this.shopName = shopName;
this.shopDescription = shopDescription;
this.radius = radius;
this.latitude = latitude;
this.longitude = longitude;
this.isFavouriteShop = isFavouriteShop;
}
public Shop(int id, String shopName, String shopDescription, int radius, String latitude, String longitude, int isFavouriteShop) {
this.id = id;
this.shopName = shopName;
this.shopDescription = shopDescription;
this.radius = radius;
this.latitude = latitude;
this.longitude = longitude;
this.isFavouriteShop = isFavouriteShop;
}
}
ShopDao.class:
@Dao
public interface ShopDao {
@Query("SELECT * FROM shops")
LiveData<List<Shop>> getAllShops();
}
存储库:
public class ShopRepository {
private ShopDao dao;
private LiveData<List<Shop>> mAllShops;
public ShopRepository(Application application){
dao = ShopDatabase.getInstance(application).dao();
mAllShops = dao.getAllShops();
}
public LiveData<List<Shop>> getAllShops() {
return mAllShops;
}
视图模型:
public class ShopListViewModel extends ViewModel {
private LiveData<List<Shop>> mAllShops;
private ShopRepository mRepository;
public ShopListViewModel(Application application) {
mRepository = new ShopRepository(application);
mAllShops = mRepository.getAllShops();
}
public ShopListViewModel() {
}
public LiveData<List<Shop>> getAllShops() {
return mAllShops;
}
}
从 onActivityCreated
的片段调用:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(ShopListViewModel.class);
mViewModel.getAllShops().observe(this, new Observer<List<Shop>>() { //<--error
@Override
public void onChanged(List<Shop> shops) {
adapter.setList(shops);
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
}
加上数据库:
@Database(entities = {Shop.class}, version = 1, exportSchema = false)
public abstract class ShopDatabase extends RoomDatabase {
public abstract ShopDao dao();
private static volatile ShopDatabase INSTANCE;
public static ShopDatabase getInstance(final Context context){
if (INSTANCE == null){
synchronized (ShopDatabase.class){
if (INSTANCE == null){
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
ShopDatabase.class,
"shop_database.db")
.build();
}
}
}
return INSTANCE;
}
}
我的 gradle 依赖项:
implementation 'androidx.room:room-runtime:2.1.0-alpha03'
annotationProcessor 'androidx.room:room-compiler:2.1.0-alpha03'
// ViewModel and LiveData
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha01'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.1.0-alpha01'
我的项目迁移到 Android X 所以我使用了那些。
我可以向数据库添加任何问题的项目,它们已保存并可用。
你们有谁能看到我做的任何赌注吗?
提前致谢!
mAllShops
变量在接受类型 Application
参数的构造函数中初始化。但是那个构造函数永远不会被调用。当您在 Fragment
中获取 ViewModel
时,它默认调用无参数构造函数。要让它调用您的参数化构造函数,您需要创建一个 ViewModelProvider.Factory
.
尝试阅读 this
的 "ViewModel with non-default constructor" 部分
我使用 MVVM 模式和 LiveData 创建了简单的应用程序来观察数据。我显示的列表显示在片段中。对我来说,一切似乎都很好,因为我将我的代码与其他有效的示例进行了比较,但没有发现任何错误。
当 activity 启动时,我交换片段并在 onActivityCreated
行 mViewModel.getAllShops().observe(this, new Observer<List<Shop>>() { //<--error
中出现以下错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference
我的架构是:
- 实体 - Shop.class
- 道 - ShopDao.class
- 资料库 - ShopRepository.class
- ViewModel - ShopListViewModel
- 在 RecyclerView 中显示数据的片段 - ShopList.java
Shop.class:
@Entity(tableName = "shops")
public class Shop {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
public int id;
@ColumnInfo(name = "shop_name")
public String shopName;
@ColumnInfo(name = "shop_description")
public String shopDescription;
@ColumnInfo(name = "radius")
public int radius;
@ColumnInfo(name = "latitude")
public String latitude;
@ColumnInfo(name = "longitude")
public String longitude;
@ColumnInfo(name = "isFavourite")
public int isFavouriteShop;
public int getId() {
return id;
}
public String getShopName() {
return shopName;
}
public String getShopDescription() {
return shopDescription;
}
public int getRadius() {
return radius;
}
public String getLatitude() {
return latitude;
}
public String getLongitude() {
return longitude;
}
public int getIsFavouriteShop() {
return isFavouriteShop;
}
@Ignore
public Shop(String shopName, String shopDescription, int radius, String latitude, String longitude, int isFavouriteShop) {
this.shopName = shopName;
this.shopDescription = shopDescription;
this.radius = radius;
this.latitude = latitude;
this.longitude = longitude;
this.isFavouriteShop = isFavouriteShop;
}
public Shop(int id, String shopName, String shopDescription, int radius, String latitude, String longitude, int isFavouriteShop) {
this.id = id;
this.shopName = shopName;
this.shopDescription = shopDescription;
this.radius = radius;
this.latitude = latitude;
this.longitude = longitude;
this.isFavouriteShop = isFavouriteShop;
}
}
ShopDao.class:
@Dao
public interface ShopDao {
@Query("SELECT * FROM shops")
LiveData<List<Shop>> getAllShops();
}
存储库:
public class ShopRepository {
private ShopDao dao;
private LiveData<List<Shop>> mAllShops;
public ShopRepository(Application application){
dao = ShopDatabase.getInstance(application).dao();
mAllShops = dao.getAllShops();
}
public LiveData<List<Shop>> getAllShops() {
return mAllShops;
}
视图模型:
public class ShopListViewModel extends ViewModel {
private LiveData<List<Shop>> mAllShops;
private ShopRepository mRepository;
public ShopListViewModel(Application application) {
mRepository = new ShopRepository(application);
mAllShops = mRepository.getAllShops();
}
public ShopListViewModel() {
}
public LiveData<List<Shop>> getAllShops() {
return mAllShops;
}
}
从 onActivityCreated
的片段调用:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(ShopListViewModel.class);
mViewModel.getAllShops().observe(this, new Observer<List<Shop>>() { //<--error
@Override
public void onChanged(List<Shop> shops) {
adapter.setList(shops);
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
}
加上数据库:
@Database(entities = {Shop.class}, version = 1, exportSchema = false)
public abstract class ShopDatabase extends RoomDatabase {
public abstract ShopDao dao();
private static volatile ShopDatabase INSTANCE;
public static ShopDatabase getInstance(final Context context){
if (INSTANCE == null){
synchronized (ShopDatabase.class){
if (INSTANCE == null){
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
ShopDatabase.class,
"shop_database.db")
.build();
}
}
}
return INSTANCE;
}
}
我的 gradle 依赖项:
implementation 'androidx.room:room-runtime:2.1.0-alpha03'
annotationProcessor 'androidx.room:room-compiler:2.1.0-alpha03'
// ViewModel and LiveData
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha01'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.1.0-alpha01'
我的项目迁移到 Android X 所以我使用了那些。
我可以向数据库添加任何问题的项目,它们已保存并可用。
你们有谁能看到我做的任何赌注吗?
提前致谢!
mAllShops
变量在接受类型 Application
参数的构造函数中初始化。但是那个构造函数永远不会被调用。当您在 Fragment
中获取 ViewModel
时,它默认调用无参数构造函数。要让它调用您的参数化构造函数,您需要创建一个 ViewModelProvider.Factory
.
尝试阅读 this
的 "ViewModel with non-default constructor" 部分