Невозможно наблюдать нулевые данные - MVVM с Livedata - PullRequest
0 голосов
/ 31 декабря 2018

Я создал простое приложение, используя шаблон MVVM с LiveData для наблюдения за данными.Список, который я отображаю, отображается фрагментом.Мне кажется, все в порядке, так как я сравнил свой код с другими моими примерами, которые работают, и я не нашел ничего плохого.

Когда начинается действие, я меняю фрагменты и в 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

моя схема:
- Entity - Shop.class
- Dao - 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;
    }

ViewModel:

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, поэтомуЯ использовал их.

Я могу добавлять элементы в базу данных с любой проблемой, они сохраняются и доступны.

Может ли кто-нибудь из вас увидеть какую-либо ошибку, которую я совершил?
Заранее спасибо!

1 Ответ

0 голосов
/ 31 декабря 2018

Переменная mAllShops инициализируется в конструкторе, который принимает параметр типа Application.Но этот конструктор никогда не вызывается.Когда вы получаете ViewModel в вашем Fragment, он по умолчанию вызывает конструктор без параметров.Чтобы он вызывал ваш параметризованный конструктор, вам нужно создать ViewModelProvider.Factory.

Попробуйте прочитать раздел «ViewModel с конструктором не по умолчанию» в this

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...