无法观察空数据-具有Livedata的MVVM

时间:2018-12-31 12:14:09

标签: java android sqlite android-architecture-components

我已经使用MVVM模式和LiveData创建了一个简单的应用程序来观察数据。我显示的列表显示在一个片段中。对我来说,一切似乎都还不错,因为我将代码与可以正常工作的其他示例进行了比较,发现没有错误。

活动开始后,我交换了片段,在onActivityCreated的{​​{1}}行中,出现以下错误:

mViewModel.getAllShops().observe(this, new Observer<List<Shop>>() { //<--error

我的模式是:
-实体-Shop.class
-道-ShopDao.class
-存储库-ShopRepository.class
-ViewModel-ShopListViewModel
-在RecyclerView中显示数据的片段-ShopList.java

Shop.class:

java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference

ShopDao.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;
    }
}

存储库:

@Dao
public interface ShopDao {

    @Query("SELECT * FROM shops")
    LiveData<List<Shop>> getAllShops();
}

ViewModel:

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

我的gradle依赖项:

@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;
    }

}

我的项目已迁移到Android X,所以我使用了它们。

我可以将任何有问题的项目添加到数据库中,它们可以保存并可用。

你们中的任何人都能看到我所做的任何错误吗?
预先感谢!

1 个答案:

答案 0 :(得分:1)

mAllShops变量在构造函数中初始化,该构造函数接受类型为Application的参数。但是从未调用过该构造函数。当您将ViewModel放入Fragment中时,默认情况下它将调用无参数构造函数。要使其调用您的参数化构造函数,您需要创建一个ViewModelProvider.Factory

尝试阅读this的“使用非默认构造函数的ViewModel”部分