Android MVVM 和 Retrofit api 响应为空

Posted

技术标签:

【中文标题】Android MVVM 和 Retrofit api 响应为空【英文标题】:Android MVVM and Retrofit api response is null 【发布时间】:2019-09-03 01:32:39 【问题描述】:

该函数用于登录用户。我正在使用数据绑定和 RxJava

public void loginUser(String idNumber, String password) 
    RetrofitService.getApiService()
            .agentLogin(new LoginRequest(idNumber, password))
            .subscribeOn(Schedulers.io())
            .observeOn(androidSchedulers.mainThread())
            .subscribe(new Action1<Response<LoginResponse>>() 
                @Override
                public void call(Response<LoginResponse> userResponse) 
                    if (userResponse.isSuccessful() ) 
                        executor.execute(new Runnable() 
                            @Override
                            public void run() 

                                Log.i("AUTHKEY",userResponse.body().getUser().getAuthKey());
                                userDao.insert(userResponse.body().getUser());
                            
                        );
                    
                
            );


当我登录Log.i("AUTHKEY",userResponse.body().getUser().getAuthKey());时应用程序失败

错误java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Integer com.vuna.agent.model.LoginResponse$User.getId()' on a null object reference

从 Okhttp 记录器,服务器返回正确的响应

2019-04-12 12:33:36.707 28896-29064/com.vuna.agent D/OkHttp: <-- 200 OK http://example.com/login (923ms)

2019-04-12 12:33:36.709 28896-29064/com.vuna.agent D/OkHttp: "code":201,"message":"You are now logged in!","id":2,"firstname":"Victor","lastname":"Amwollo","authkey":"22sA1JvVo4hmzhps1NVIO7_B6f4yCp_e"
2019-04-12 12:33:36.709 28896-29064/com.vuna.agent D/OkHttp: <-- END HTTP (141-byte body)

这是带有内部实体类的 LoginResponse 类

public class LoginResponse 

    private Boolean success;

    private User user;


    public User getUser() 
        return user;
    

    public void setUser(User user) 
        this.user = user;
    


    @Entity(tableName = "user")
    public static class User 

        @PrimaryKey(autoGenerate = true)
        @SerializedName("id")
        private Integer id;

        private String firstName;
        private String lastName;

        private String authKey;

        //getters and setters

    

为什么我会收到错误消息?

【问题讨论】:

可以发帖LoginResponseclass吗? ResponseBody 可以从响应中消费一次,这就是它给出NullPointerException 的原因。尝试将其存储在局部变量中,并从该变量中进一步使用。 @Dhaiyur,我已经更新了代码,请检查 【参考方案1】:

response 上的response.body() 方法将读取输入(network) 流并将其转换为字符串。因此它会动态构建字符串并将其返回给您。第二次调用时,网络流已经被消耗,不再可用。

因此,解决方案是将响应的结果保存到一个变量中,然后根据需要多次访问它。

查看以下代码:

@Override
public void call(Response<LoginResponse> userResponse) 
    if (userResponse.isSuccessful() ) 
        LoginResponse data = userResponse.body(); // Consume response body once and then use it in this method further
        executor.execute(new Runnable() 
            @Override
            public void run() 
                Log.i("AUTHKEY", data.getUser().getAuthKey()); // access data variable here
                userDao.insert(data.getUser()); // access data variable here
            
        );
    

【讨论】:

只有当你将@Streaming 添加到你的改造接口方法中时才会这样,否则网络就会在那时完成:) 是的@StuartCampbell,你是对的。我发布了我的答案,初步观察可能是这种情况。【参考方案2】:

你得到空指针是因为你的 json 没有映射到 LoginResponse。

试试

public class LoginResponse 

    private Boolean success;
    private Integer id;
    private String firstName;
    private String lastName;
    private String authKey;


我清理了你的 RX。注意:括号可能是错误的,因为我习惯了 kotlin。

public void loginUser(String idNumber, String password) 
    RetrofitService.getApiService()
        .agentLogin(new LoginRequest(idNumber, password))
        .filter  it.isSuccessful(); 
        .map  it.body(); 
        .map  new User(it.getId()...) /* covert LoginResponse to User here */  
        .flatMapCompletable  Completable.fromAction  userDao.insert(it);  
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe();                                 

【讨论】:

以上是关于Android MVVM 和 Retrofit api 响应为空的主要内容,如果未能解决你的问题,请参考以下文章

Android MVVM框架搭建OKHttp + Retrofit + RxJava

Android MVVM框架搭建OKHttp + Retrofit + RxJava

需要调用一个api来使用retrofit在android mvvm中刷新令牌,在哪里编写逻辑?

Android入门第65天-mvvm模式下的retrofit2+okhttp3+rxjava

0.Android高仿网易云音乐OkHttp+Retrofit+RxJava+Glide+MVC+MVVM

0.Android高仿网易云音乐OkHttp+Retrofit+RxJava+Glide+MVC+MVVM