Java 在非视图或非视图模型类中观察LiveData

Java 在非视图或非视图模型类中观察LiveData,java,android-livedata,Java,Android Livedata,我有一个应用程序,允许用户将其凭证输入到片段中,然后插入或更新房间数据库中的记录。事务由CredentialsRepository处理 在网络方面,我有一个数据存储库,它与NetworkServiceController一起创建对远程API的调用。为了访问远程API,我有一个拦截器,它向每个调用添加用户凭据 我需要的是在应用程序加载时以及在文件室数据库中的数据发生更改时加载这些凭据。我可以在登录屏幕(视图)中使用LiveData来完成这项工作,但是如何使用LiveData观察数据存储库中的用户凭

我有一个应用程序,允许用户将其凭证输入到片段中,然后插入或更新房间数据库中的记录。事务由CredentialsRepository处理

在网络方面,我有一个数据存储库,它与NetworkServiceController一起创建对远程API的调用。为了访问远程API,我有一个拦截器,它向每个调用添加用户凭据

我需要的是在应用程序加载时以及在文件室数据库中的数据发生更改时加载这些凭据。我可以在登录屏幕(视图)中使用LiveData来完成这项工作,但是如何使用LiveData观察数据存储库中的用户凭据数据呢

如何将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();
        }
    }
或者像这样:

credRepo.getCredentials().observeForever(credentialsObserver);
credentialsDAO.getUser().observeForever(credentialsObserver);
但是,我需要通过调用以下命令在构造函数中创建网络服务:

createNetworkService();
否则,应用程序仍会崩溃


我的应用程序现在可以通过添加上面的代码行来工作,但是出现了一个新问题。在新进程中启动应用程序时,需要几秒钟才能获得任何网络数据。我的猜测是,创建数据存储库的速度比从数据库检索数据的速度要快,并且我的网络服务最初是使用空的或未知的用户凭据创建的。这是一个正确的假设吗?

问题是我没有设置空间来允许主线程查询使用:

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。有关我如何获得此解决方案的信息,请参阅此


将来我还会创建一个日志文件,以便于故障排除。

不要认为你可以从回购中观察到,但是,您可以将这些实时数据对象返回到视图或视图模型,并从活动或片段中进行观察。让存储库将这些实时数据对象返回到活动或片段中,并从中进行观察不知道是否适合您,但为什么不在每次网络调用时获取当前凭据?这样你就不必观察他们的变化。我考虑过这一点,但我担心每次打电话都要花很多时间。我宁愿将凭据缓存在本地字段中,并且只在它们在房间中更改时更新它们。同时,在每次API调用中获取凭据会创建一个新的网络服务。。。。导致大量对象被创建。我确实尝试过这个建议,但应用程序崩溃了。
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;
}