我有一个应用程序,允许用户将其凭据输入Fragment,然后在Room数据库中插入或更新记录。交易由CredentialsRepository处理。
在网络方面,我有一个DataRepository,它与NetworkServiceController一起使用来创建对我的远程API的调用。为了访问远程API,我有一个拦截器,可将用户凭据添加到每个调用中。
我需要的是在应用程序加载时以及Room数据库中的数据更改时加载这些凭据。我可以在登录屏幕(视图)中使用LiveData来执行此操作,但是如何使用LiveData在DataRepository中观察用户凭据数据?
如何将DataRepository类注册为观察者?现在我的应用程序崩溃了……我很确定我注册观察者的方式是错误的。
这是我的凭据存储库:
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();
}
}
这是我的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 ...
}
编辑: 观察者注册可以在DataRepository中进行,如下所示:
credRepo.getCredentials().observeForever(credentialsObserver);
或类似这样:
credentialsDAO.getUser().observeForever(credentialsObserver);
但是,我需要通过调用以下内容在构造函数中创建网络服务:
createNetworkService();
否则,应用程序仍然崩溃。
我的应用程序现在可以使用上面的代码行,但是已经创建了一个新问题。在新过程中启动该应用程序时,需要花费几秒钟的时间才能获得任何网络数据。我的猜测是,DataRepository的创建速度比从数据库中检索数据的速度快,而我的网络服务最初是使用空或未知用户凭据创建的。这是正确的假设吗?
答案 0 :(得分:0)
问题是我没有设置Room来允许使用以下命令进行主线程查询:
allowMainThreadQueries()
用法:
public static CredentialsDatabase getDatabase(final Context context)
{
if (INSTANCE == null)
{
synchronized (CredentialsDatabase.class)
{
if (INSTANCE == null)
{
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
CredentialsDatabase.class, "credentials_database")
.addCallback(initializeCallback)
//allow main thread queries only used for DataRepository instantiation as
//credentials are required to set up network services.
.allowMainThreadQueries()
.build();
}
}
}
return INSTANCE;
}
创建DataRepository时,我需要持久保存在内存中的UserCredentials的值,以便在我的视图处于活动状态时可以立即进行网络调用。我还在DAO中创建了一个查询,该查询返回了没有包装在LiveData对象中的UserCredentials。有关如何使用此解决方案的信息,请参阅此Stackoverflow post。
将来,我还将创建一个日志文件,以方便进行故障排除。