I have an application that allows a user to enter their credentials into a Fragment which then inserts or updates a record in a Room database. The transaction is handled by a CredentialsRepository.
On the networking side, I have a DataRepository that works with a NetworkServiceController to create calls to my remote API. In order to access the remote API I have an interceptor that adds the user credentials to each call.
What I need is to load those credentials when the application loads, and whenever the data in the Room database changes. I can do this using LiveData in my login screen (a View), but how can I observe the user credential data in my DataRepository using LiveData?
How do I register my DataRepository class as an Observer? Right now my app crashes...I am pretty sure the way I am registering the observer is wrong.
Here is my CredentialsRepository:
import androidx.lifecycle.LiveData;
import ca.thirdgear.homeautomation.HomeAutomationApp;
import ca.thirdgear.homeautomation.dao.UserCredentialsDAO;
import ca.thirdgear.homeautomation.entity.UserCredentials;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Repository Class for data from the Room Database
*/
@Singleton
public class CredentialsRepository
{
@Inject
UserCredentialsDAO credentialsDAO;
@Inject
public CredentialsRepository()
{
HomeAutomationApp.getAppComponent().inject(this);
}
public void setCredentials(String userEmail, String password)
{
//create UserCredentials object with the credentials provided from the UI.
UserCredentials newOrUpdatedUserCredentials = new UserCredentials(userEmail, password);
//insert user credentials into the database
Runnable myRunnableObject = new SetUserCredentials(credentialsDAO, newOrUpdatedUserCredentials);
new Thread(myRunnableObject).start();
}
public LiveData<UserCredentials> getCredentials()
{
return credentialsDAO.getUser();
}
}
Here is my DataRepositoryClass
/**
* Repository class for handling network calls to REST API
*/
@Singleton
public class DataRepository
{
//Network components
@Inject
NetworkServiceController networkServiceController;
@Inject
UserCredentialsDAO credentialsDAO;
@Inject
CredentialsRepository credRepo;
private HomeAutomationAPI homeAutomationAPIService;
private MutableLiveData<String> zoneOneState;
private MutableLiveData<String> zoneTwoState;
private MutableLiveData<String> garageDoorState;
private MutableLiveData<String> adtSystemState;
private MutableLiveData<String> panelTemperature;
private String username;
private String password;
@Inject
public DataRepository()
{
//Inject Network Backend Components & Room DAO
HomeAutomationApp.getAppComponent().inject(this);
//create credentials observer
final Observer<UserCredentials> credentialsObserver = new Observer<UserCredentials>() {
@Override
public void onChanged(UserCredentials userCredentials)
{
//update string values for credentials
username = userCredentials.getUsername();
password = userCredentials.getPassword();
//call createNetworkService() to create a new network service object
createNetworkService();
}
};
//register the observer
//this does not work...app crashes
credRepo.getCredentials().observeForever(credentialsObserver);
zoneOneState = new MutableLiveData<>();
zoneTwoState = new MutableLiveData<>();
garageDoorState = new MutableLiveData<>();
adtSystemState = new MutableLiveData<>();
panelTemperature = new MutableLiveData<>();
//Poll the server every 5 seconds on a separate thread for changes in the IO
Thread thread = new Thread(new Runnable(){
public void run()
{
// Moves the current Thread into the background
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
while(true)
{
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
getIoStatus();
}
}
});
thread.start();
}
/*
Create the network service when there are changes in the user credentials data.
*/
private void createNetworkService()
{
homeAutomationAPIService = networkServiceController.createService(HomeAutomationAPI.class, username, password);
}
... deleted methods not relevant ...
}
EDIT: Observer registration can occur in DataRepository like this:
credRepo.getCredentials().observeForever(credentialsObserver);
or like this:
credentialsDAO.getUser().observeForever(credentialsObserver);
However, I need to create the network service in the constructor by calling:
createNetworkService();
Otherwise the application still crashes.
My application now works with the addition of the line of code above, but a new problem has been created. When the application is launched in a new process, it takes several seconds before any network data is available. My guess is that DataRepository creation takes place faster than data can be retrieved from the database, and my network services is initially created with null or unknown user credentials. Is this a correct assumption?