Как загрузить несколько AndroidViewModel в одном действии, чтобы получить доступ к LiveData, который возвращает значение из нескольких таблиц, используя Room - PullRequest
0 голосов
/ 30 мая 2018

Я занимаюсь разработкой приложения для электронной коммерции в Android, где мне нужно создать несколько таблиц, вставить в них данные и извлечь данные в активности / фрагментах из этой таблицы (загрузить значение в Spinner, подзапрос на основе условий выполнения и т. Д.).Для этого я объявил 2 таблицы.Адрес, Банк, как показано ниже

Bank.java

@Entity
public class Bank {

    @PrimaryKey(autoGenerate = true)
    public int id;
    public String bankId;
    public String bankName;
    public String bankType;

    public Bank() {
    }

    public String getBankId() {
        return bankId;
    }

    public String getBankName() {
        return bankName;
    }

    public String getBankType() {
        return bankType;
    }
}

Address.java

@Entity
public class Address {

    @PrimaryKey(autoGenerate = true)
    public int id;
    public String state;
    public String district;
    public String block;
    public String id_panchayat;
    public String panchayat;

    public Address() {
    }

    public String getState() {
        return state;
    }

    public String getDistrict() {
        return district;
    }

    public String getBlock() {
        return block;
    }

    public String getId_panchayat() {
        return id_panchayat;
    }

    public String getPanchayat() {
        return panchayat;
    }
}

И ДаоКласс для этих двух таблиц:

BankDao.java

@Dao
public interface BankDao {

    @Insert(onConflict = REPLACE)
    void insertSingleBank (Bank bank);

    @Insert(onConflict = REPLACE)
    void insertMultipleBank (List<Bank> bankList);

    @Query("SELECT * FROM Bank")
    LiveData<List<Bank>> getAllBank();

    @Query("SELECT bankName FROM Bank")
    List<String> getAllBankData ();

    @Query("SELECT * FROM Bank WHERE bankName = :bankName")
    Bank getBankSubData (String bankName);

    @Query("DELETE FROM Bank")
    void deleteBank();
}

AddressDao.java

@Dao
public interface AddressDao {

    @Insert(onConflict = REPLACE)
    void insertSingleAddress(Address address);

    @Insert(onConflict = REPLACE)
    void insertMultipleAddress(List<Address> addressList);

    @Query("SELECT * FROM Address")
    LiveData<List<Address>> getAllAddress();

    @Query("SELECT state FROM Address")
    List<String> getAllStateList();

    @Query("SELECT district FROM Address WHERE state = :state")
    List<String> getDistrictListAll(String state);

    @Query("SELECT block FROM Address WHERE state = :state AND district = :district")
    List<String> getBlockListAll(String state, String district);

    @Query("SELECT panchayat FROM Address WHERE state = :state AND district = :district AND block = :block")
    List<String> getPanchayatListAll(String state, String district, String block);

    @Query("DELETE FROM Address")
    void deleteAddress();
}

ИViewModel для этих двух классов:

AddressModel.java

public class AddressModel extends AndroidViewModel {

    private RoomDatabaseHelper roomDatabase;
    private final LiveData<List<Address>> getAllAddress;

    public AddressModel(Application application) {
        super(application);
        roomDatabase = RoomDatabaseHelper.getInstance(this.getApplication());
        getAllAddress = roomDatabase.daoAddress().getAllAddress();
    }

    public void insertSingleAddress(Address address) {
        new InsertSingleAddressAsyncTask(roomDatabase).execute(address);
    }

    private static class InsertSingleAddressAsyncTask extends AsyncTask<Address, Void, Void> {

        private RoomDatabaseHelper db;

        InsertSingleAddressAsyncTask(RoomDatabaseHelper userDatabase) {
            db = userDatabase;
        }

        @Override
        protected Void doInBackground(Address...params) {
            db.daoAddress().insertSingleAddress(params[0]);
            return null;
        }
    }

    public void insertMultipleAddress(List<Address> registrationList) {
        new InsertMultipleAddressAsyncTask(roomDatabase).execute(registrationList);
    }

    private static class InsertMultipleAddressAsyncTask extends AsyncTask<List<Address>, Void, Void> {

        private RoomDatabaseHelper db;

        InsertMultipleAddressAsyncTask(RoomDatabaseHelper userDatabase) {
            db = userDatabase;
        }

        @Override
        protected Void doInBackground(List<Address>...params) {
            db.daoAddress().insertMultipleAddress(params[0]);
            return null;
        }
    }

    public LiveData<List<Address>> getAllAddress() {
        return getAllAddress;
    }
}

BankModel.java

public class BankModel extends AndroidViewModel {

    private RoomDatabaseHelper roomDatabase;
    private final LiveData<List<Bank>> getAllBank;

    public BankModel(Application application) {
        super(application);
        roomDatabase = RoomDatabaseHelper.getInstance(this.getApplication());
        getAllBank = roomDatabase.daoBank().getAllBank();
    }

    public void insertSingleBank(Bank bank) {
        new InsertSingleBankAsyncTask(roomDatabase).execute(bank);
    }

    private static class InsertSingleBankAsyncTask extends AsyncTask<Bank, Void, Void> {

        private RoomDatabaseHelper db;

        InsertSingleBankAsyncTask(RoomDatabaseHelper userDatabase) {
            db = userDatabase;
        }

        @Override
        protected Void doInBackground(Bank...params) {
            db.daoBank().insertSingleBank(params[0]);
            return null;
        }
    }

    public void insertMultipleBank(List<Bank> registrationList) {
        new InsertMultipleBankAsyncTask(roomDatabase).execute(registrationList);
    }

    private static class InsertMultipleBankAsyncTask extends AsyncTask<List<Bank>, Void, Void> {

        private RoomDatabaseHelper db;

        InsertMultipleBankAsyncTask(RoomDatabaseHelper userDatabase) {
            db = userDatabase;
        }

        @Override
        protected Void doInBackground(List<Bank>...params) {
            db.daoBank().insertMultipleBank(params[0]);
            return null;
        }
    }

    public LiveData<List<Bank>> getAllBank() {
        return getAllBank;
    }
}

Класс RoomDatabase равен

RoomDatabaseHelper.java

@Database(entities = {Address.class, Bank.class}, version = 1, exportSchema = false)
public abstract class RoomDatabaseHelper extends RoomDatabase {

    private static RoomDatabaseHelper sInstance;

    public static synchronized RoomDatabaseHelper getInstance(Context context) {
        if (sInstance == null) {
            sInstance = Room.databaseBuilder(context.getApplicationContext(), RoomDatabaseHelper.class, "DemoTable").build();
        }
        return sInstance;
    }

    public abstract AddressDao daoAddress();

    public abstract BankDao daoBank();
}

и в моем фрагменте:

BankModel bankModel = ViewModelProviders.of(this).get(BankModel.class);
AddressModel addressModel = ViewModelProviders.of(this).get(AddressModel.class);

Теперь согласно документации для доступа к getAllBank() и getAllAddress() из обоих классов Model Я должен определить так

addressModel.getAllAddress().observe(mActivity, new Observer<List<Address>>() {
    @Override
    public void onChanged(List<Address> addressList) {
    }
});

addressModel.getAllBank().observe(mActivity, new Observer<List<Bank>>() {
    @Override
    public void onChanged(final List<Bank> bankList) {
    }
});

Теперь оба метода AsyncTask как вещь.Таким образом, на нагрузке активности я не могу изменить вещи, связанные с пользовательским интерфейсом.Я должен поместить весь пользовательский интерфейс под onChange.Как я могу получить доступ к обоим наблюдателям одновременно.Причина вложенного наблюдателя не является правильным решением.А также мне нужно много сложных запросов к базе данных.Поэтому для этого я должен определить так много наблюдателей или есть какие-то другие решения.

1 Ответ

0 голосов
/ 11 сентября 2018

Прежде всего, ViewModels следует использовать в качестве помощников для фрагментов или действий, чтобы получать и обрабатывать необходимые данные для представлений.Таким образом, одна активность / фрагмент должен иметь одну модель представления.И здесь вы используете их как своего рода репозитории.

Если вы все еще хотите использовать их следующим образом: How can I access both observer at the same

в обоих onChanged, вызовите метод, подобный tryUpdateUi(), где вы проверяете, оба лиgetAllBank().getValue() и getAllAddress().getValue() не равны нулю.Если это так, вы можете выполнять обновление / вычисления и т. Д.

Хотя я бы предпочел выполнить эту проверку и обработку данных во ViewModel, используя другую LiveData для передачи обработанных моделей во Fragment.Этого можно достичь с помощью MediatorLiveData, docs

...