I am developing an E-Commerce app in android where I have to create multiple Table, insert data on it and fetch data in activity/fragments from that table (Load value in Spinner, run condition based sub query etc.). For that I declared 2 tables. Address, Bank like below
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;
}
}
And the Dao class for these two tables are:
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();
}
And the ViewModel for those two classes are
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;
}
}
The RoomDatabase class is
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();
}
and in my Fragment:
BankModel bankModel = ViewModelProviders.of(this).get(BankModel.class);
AddressModel addressModel = ViewModelProviders.of(this).get(AddressModel.class);
Now according to documentation to access the getAllBank()
and getAllAddress()
from both Model class I have to define like this
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) {
}
});
now both method are AsyncTask
like thing. So on activity load I cant change the UI related thing. I have to place the whole UI under onChange
. How can I access both observer at the same. Cause nested observer is not the right solution. And also I need many complex database query. So for that I have to define so many observer or is there any other solutions.
First of all, ViewModels should be used as helpers for fragments or activities, to retrieve and process the required data for the views. Thus, one Activity/Fragment should have one viewmodel. And here you use them as some sort of repositories.
If you still wanna use them like that:
How can I access both observer at the same
on both onChanged call a method like tryUpdateUi()
where you check if both getAllBank().getValue()
and getAllAddress().getValue()
are not null. If so, you can do the updating/calculations etc.
Although I would prefer doing this check and the data processing in the ViewModel, using another LiveData to pass the processed models to Fragment. It can be achieved with MediatorLiveData, docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With