【问题标题】:Room + Live Data Debugging [closed]房间+实时数据调试[关闭]
【发布时间】:2018-07-13 08:44:50
【问题描述】:

我正在尝试创建一个登录功能,该功能将检查用户名是否存在于 db:-

我需要成功地从 Room 数据库获取实时数据到 Repository 到 view-model。下面是代码。它不起作用,但会尝试其中一个建议。

当我从 DB 行加载时:-

 UserDetails= dao.loadUserDetails(UserName);
    Log.v("Response", UserDetails.getValue().getToken());

我无法调用 Null .....

我对实现这样一个功能的最佳方法以及如何解决这个问题感到困惑。

存储库

public MutableLiveData<String> LoginUser(String UserName,String Password ) {
//
//        rUserDetails.setUsername("nadeem");
//        rUserDetails.setPassword("test");
//        rUserDetails.setToken(AppConstants.PARAMS);
//        rUserDetails.setSid("1234");
//        rUserDetails.setResourcId(Long.valueOf(12134));
//        insert(rUserDetails);


     UserDetails= dao.loadUserDetails(UserName);
    Log.v("Response", UserDetails.getValue().getToken());

    if(UserDetails.getValue()!=null) {
        rUserDetails.setUsername(UserName);
        rUserDetails.setPassword(Password);
        rUserDetails.setToken(AppConstants.PARAMS);
        Observable<MainResponse> mainResponseObserver = mtsAPI.GetSessionID("token/login", AppConstants.PARAMS + "");
        mainResponseObserver.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<MainResponse>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(MainResponse mainResponse) {
                        Log.v("Response", mainResponse.getEid());
                        if (mainResponse.getEid()==null) {
                            msessionId.postValue("Token Error");
                        }
                        else {
                            msessionId.postValue("1");
                            rUserDetails.setSid(mainResponse.getEid());

               rUserDetails.setResourcId(mainResponse.getUserVO().getBact());
                            insert(rUserDetails);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
   }
   else {
        msessionId.postValue("E");
    }
    return msessionId;

}

我被困在检查用户数据是否在 Room DB 中的部分。如果在房间数据库中,它会返回 UserDetails,这是一个可变的实时数据。

我已经测试了数据库。当我分别测试它们时,它成功插入并成功读取。

道

@Dao
public interface UserLoginDetailsDao {
    @Insert(onConflict = REPLACE)
    void save(UserLoginDetails user);
    @Query("SELECT sid, Username, Password,ResourcId,Token  FROM 
    UserLogins_tbl 
    WHERE Username = :userId")
    LiveData<UserLoginDetails> loadUserDetails(String userId);
}

使用上面的代码,我无法在 UserDetails.getvalue.getToken 上调用 Null....

【问题讨论】:

    标签: java android sqlite android-room android-livedata


    【解决方案1】:

    您正在使用LiveData 获取此 Dao 方法中声明的用户详细信息

    LiveData<UserLoginDetails> loadUserDetails(String userId);
    

    您不能直接在LiveData 上调用getValue() 并期望 获取当前值。 LiveData 需要首先计算观察者。在这种情况下,不会同步获取值。 你可以找到同样的问题here

    要使用LiveData,您需要通过传递LifecycleOwner 来观察变化,例如Activity,就像他们在架构组件示例中给出的那样 - ProductFragment

    // Observe product data
    model.getObservableProduct().observe(this, new Observer<ProductEntity>() {
        @Override
        public void onChanged(@Nullable ProductEntity productEntity) {
            model.setProduct(productEntity);
        }
    });
    

    如果你想要没有观察者的值,你可以像这样将返回类型更改为非LiveData

    UserLoginDetails loadUserDetails(String userId);
    

    在这种情况下,您不能在 ma​​in 线程上调用此方法。您需要在后台线程上调用此数据库同步操作方法,例如使用Schedulers.io() 线程使用RxJava。

    可能的解决方案是使用带有 Room 的 RxJava 返回用户数据的 Flowable,例如架构组件示例中所示 - UserDao.java

    更改您的 loadUserDetails 以返回 Flowable

    Flowable<UserLoginDetails?> loadUserDetails(String userId);
    

    订阅那个Flowablelike - UserViewModel.java

    // Map the result to desired format
    // Using RxJava operators to perform checks
    // If user is null or not
    public void checkUserExists(String userId) {
        dao.loadUserDetails(userId)
            .map(new Function<UserLoginDetails, Boolean>() {
                @Override
                public Boolean apply(UserLoginDetails userLoginDetails) throws Exception {
                    if(userLoginDetails == null){
                        return false;
                    } else {
                        return true;
                    }
                }
            })
            .subscribe(getObserver());
    }
    

    因此,当您获得 Flowable 时,您可以应用各种运算符来检查您想要的 条件,并可以将此 stream 转换为 boolean observable价值取决于您的条件。对于这个特定的用例,这将是一种非常简单且可维护的方法。

    【讨论】:

    • 感谢这确实帮助分配。将尝试重新编辑问题
    • 我只是好奇你认为这是为用户实现登录的正确方法吗?还是有更好的方法.. 因为我只是一个新手.. 最后我在实施您的第一部分建议后遇到了一个令人敬畏的问题 public void onChanged(@Nullable ProductEntity productEntity) { model.setProduct(productEntity);我现在似乎将数据获取到我的活动中,但现在每次单击登录时,显示登录成功或失败的警报对话框大约出现 3 到 4 次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    相关资源
    最近更新 更多