获取 LiveData 的初始值总是返回 Null

Cha*_*iwa 5 java android synchronous android-room android-livedata

当应用程序启动时,我试图从本地房间数据库加载登录用户。如果之前保存的用户的身份验证令牌仍然有效,我想跳过提示用户登录!

因此,从DAO 中,我想返回一个包含先前登录用户LiveData对象,然后观察它以进行后续更改。我面临的挑战是,如果我将结果包装在LiveData 中,获取当前登录用户的方法总是返回 null,但如果作为POJO返回,它返回预期的用户。

我怎么能强迫LiveData运行同步只是初始化,然后其后听的后续变化?我真的希望这两种行为结合起来作为身份验证可能无效后台同步任务时,或者当用户注销(这些行动将更换或更新保存令牌,我想是反应性的,以这样的更新的帮助下实时数据)。

这是我迄今为止尝试过的:

授权DAO.java

public interface AuthorizationDAO {

    @Query("SELECT * FROM Authorization LIMIT 1") //Assume only one Authentication token will exist at any given time
    LiveData<Authorization> getLoggedInUser(); //I want to keep this behaviour

    @Insert(onConflict = REPLACE)
    long insertAuth(Authorization authorization);

    @Update
    void logoutCurrentUser(Authorization authorization);


}
Run Code Online (Sandbox Code Playgroud)

AuthorizationRepository.java

public class AuthorizationRepository {
    private AuthorizationDAO mAuthorizationDAO;

    private MutableLiveData<Authorization> mAuthorization = new MutableLiveData<>();

    public AuthorizationRepository(Application application){

        AppDatabase db = AppDatabase.getDatabase(application);

        this.mAuthorizationDAO = db.mAuthorizationDAO();
    }

    public LiveData<Authorization> getLoggedInUser(){
               mAuthorization.postValue(mAuthorizationDAO.getLoggedInUser().getValue()); //this is always null at startup
        return this.mAuthorization;
    }
Run Code Online (Sandbox Code Playgroud)

授权视图模型.java

public class AuthorizationViewModel extends AndroidViewModel {

    private AuthorizationRepository mAuthorizationRepository;

    private LiveData<Resource<Authorization>> mAuthorization;
    private LiveData<Authorization> loggedInUserAuth;

    public AuthorizationViewModel(@NonNull Application application) {
        super(application);
        this.mAuthorizationRepository = new AuthorizationRepository(application);

    }
    public void init(){
        this.loggedInUserAuth = this.mAuthorizationRepository.getLoggedInUser();
    }
    public LiveData<Authorization> getLoggedInUserAuth() {
        return this.loggedInUserAuth;
    }
}
Run Code Online (Sandbox Code Playgroud)

应用活动.java

public class AppActivity extends AppCompatActivity {
    public AuthorizationViewModel mAuthorizationViewModel;
    public  @Nullable Authorization mAuthorization;
    private NavController mNavController;
    private NavHostFragment mNavHostFragment;
    private BottomNavigationView mBottomNavigationView;
    private boolean mIsLoggedIn;
    private ActivityAppBinding mBinding;
    private boolean mIsTokenExpired;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_app);

        mNavHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.app_nav_host_fragment);
        mNavController = mNavHostFragment.getNavController();

        mBottomNavigationView = findViewById(R.id.nav_bottom_nav_view);
        NavigationUI.setupWithNavController(mBottomNavigationView, mNavController);

        if (Build.VERSION.SDK_INT>9){

            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }

        mAuthorizationViewModel = ViewModelProviders.of(this).get(AuthorizationViewModel.class);

        mAuthorizationViewModel.init(); //Here I want to load user synchronously before the rest happens and then on next line observe the same object

        mAuthorizationViewModel.getLoggedInUserAuth().observe(this, new Observer<Authorization>() {
            @Override
            public void onChanged(@Nullable Authorization authorization) {
                mBinding.setViewModel(authorization);
                mIsLoggedIn = authorization == null? false: authorization.isLoggedIn();
                mIsTokenExpired = authorization == null ? true : authorization.isTokenExpired();
                if(!mIsLoggedIn || mIsTokenExpired){
                    if (authorization != null){

                        Log.i("CurrentAuth", "mIsLoggedIn?: "+authorization.isLoggedIn());
                        Log.i("CurrentAuth", "isTokenExpired?: "+authorization.isTokenExpired());
                        Log.i("CurrentAuth", "tokenCurrentTime?: "+ Calendar.getInstance().getTime());
                        Log.i("CurrentAuth", "tokenIssuedAt?: "+ authorization.getIat());
                        Log.i("CurrentAuth", "tokenExpiresAt?: "+ authorization.getExp());
                    }
                    mNavController.navigate(R.id.start_login);
                }
            }
        });
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我打电话mAuthorizationViewModel.init() ,所以我可以加载或初始化loggedInUserAuth本地数据库中,然后观察同一LiveData与实例mAuthorizationViewModel.getLoggedInUserAuth()。观察()下一行!但返回的值loggedInUserAuth总是空

请帮忙,谢谢!

Kri*_*rma 1

mAuthorization在类中创建一个getter方法AuthorizationRepository

public MutableLiveData<Authorization> getAuthorizationResult() {
   return mAuthorization;
}
Run Code Online (Sandbox Code Playgroud)

然后修改你的AuthorizationViewModel类如下

public void init() {
    mAuthorizationRepository.getLoggedInUser();
}

public LiveData<Authorization> getLoggedInUserAuth() {
    return mAuthorizationRepository.getAuthorizationResult();
}
Run Code Online (Sandbox Code Playgroud)