为什么我的活动没有看到观察到的物体变化?[已解决]

时间:2019-07-25 20:15:31

标签: android mvvm retrofit2 android-livedata

我是Android开发的新手,我正在尝试了解MVVM架构的实时数据。 我试图使主活动识别属于活动视图模型的对象中的更改。

我创建了一个简单的登录活动,该活动从用户名和密码字段获取文本并将其传递给视图模型的登录功能,然后该功能将数据发送到用户存储库,然后向Spring发出POST请求-在我的PC上运行的服务器。 如果用户名和密码正确,则存储库登录功能将返回具有已登录用户名的MutableLiveData对象,否则返回null。 存储库工作正常(从服务器返回的数据正确)。视图模型的字段类型为MutableLiveData,在调用登录函数后需要对其进行更新。在活动中,应该有一个观察者,该事件应在loginInUser字段(类型为MutableLiveData)中发生更改时得到通知,即使发生更改,也永远不会激活该观察者的onChange函数。

我希望有一些代码可以帮助我更好地解释。

主要活动:

public class MainActivity extends AppCompatActivity {
        public EditText usernameTxt;
        public EditText passwordTxt;
        public Button loginBtn;
        public String loggedInuUser;
        LoginViewModel loginViewModel;


    @Override
    protected void onCreate(Bundle savedInstanceState) {



        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        usernameTxt = findViewById(R.id.usernameTxt);
        passwordTxt   = findViewById(R.id.passwordTxt);
        loginBtn   = findViewById(R.id.loginBtn);

        loginViewModel = ViewModelProviders.of(this ).get(LoginViewModel.class);
        loginViewModel.init();
        try {
            loginViewModel.getLoggedInUser().observe(this, new Observer<String>() {
                        @Override
                        public void onChanged(@Nullable String s) {
                            Toast toast=  Toast.makeText(MainActivity.this,"changed" , Toast.LENGTH_LONG );
                            toast.show();
                        }
                    }
            );
        }catch (Exception e){
            System.out.println("==========================================================");
            System.out.println( e.getMessage());
            System.out.println("==========================================================");
        }

    }


    protected void onLogInCliked(View v ){

//        Toast toast=  Toast.makeText(getApplicationContext(),loggedInuUser, Toast.LENGTH_LONG );
//        toast.show();
        loginViewModel.login(usernameTxt.getText().toString(),passwordTxt.getText().toString());
//        Toast toast2=  Toast.makeText(getApplicationContext(),loggedInuUser, Toast.LENGTH_LONG );
//        toast2.show();


    }
}

视图模型:

public class LoginViewModel extends ViewModel {


    private UsersRepository usersRepository;
    private MutableLiveData<String> loggedInUser;

    public void init(){
        if(loggedInUser!= null){
            return;
        }

        usersRepository = UsersRepository.getInstance();
        loggedInUser=new MutableLiveData<>();
    }


    public MutableLiveData<String> getLoggedInUser(){
        return loggedInUser;
    }

    public void login(String userName , String hashedPassword) {

        loggedInUser = usersRepository.login(userName, hashedPassword);
    }
}

存储库:

public class UsersRepository {

private static UsersRepository usersRepository;

public static UsersRepository getInstance(){
    if (usersRepository == null){
        usersRepository = new UsersRepository();
    }
    return usersRepository;
}

private UsersRepositoryApi usersRepositoryApi;

public UsersRepository(){
    usersRepositoryApi = RetrofitService.cteateService(UsersRepositoryApi.class);
}


public MutableLiveData<String> login(String username , String hashedPassword){
   final MutableLiveData<String> loggedInUser = new MutableLiveData<>();
    User user = new User(username,hashedPassword);

    usersRepositoryApi.login(user).enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            if (response.isSuccessful()) {
                loggedInUser.setValue(response.body());
            }
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            loggedInUser.setValue(null);
        }
    });

    return loggedInUser;
}

}

在mainActivity中,我设置了观察者,并希望该应用显示我的Toast消息,但什么也没发生。

我试图查看视图模型中发生了什么,这有点奇怪, 所以我打印了这样的东西:

    public void login(String userName , String hashedPassword) {

    System.out.println("222======================================");
    System.out.println("==========================================");
    System.out.println("==========================================");
    System.out.println(loggedInUser.getValue());
    System.out.println("==========================================");
    System.out.println("==========================================");
    System.out.println("==========================================");
    loggedInUser = usersRepository.login(userName, hashedPassword);

    System.out.println("333======================================");
    System.out.println("==========================================");
    System.out.println("==========================================");
    System.out.println(loggedInUser.getValue());
    System.out.println("==========================================");
    System.out.println("==========================================");
    System.out.println("==========================================");

}

第一次运行登录功能时,222和333的输出均为空,但是第二次运行登录功能时,222的输出为loggingInUser,333的输出为空

在两种情况下,都未观察到观察者的on change功能

有人知道我在做什么错吗?

谢谢你 罗宁!

编辑 [解] 正如Neha Rathore所建议的那样,这是对我有用的解决方案:

在视图模型中:

   public void login(String userName , String hashedPassword) {
    usersRepository.login(userName, hashedPassword, new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            loggedInUser.setValue(response.body());
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            loggedInUser.setValue(null);
        }
    }) ;

}

以及在存储库中:

    public void login(String username, String hashedPassword,@Nullable final Callback<String> callback){
    final MutableLiveData<String> loggedInUser = new MutableLiveData<>();
    User user = new User(username,hashedPassword);

    usersRepositoryApi.login(user).enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            if (response.isSuccessful()) {
                callback.onResponse(call,response);
            }
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            callback.onFailure(call,t);
        }
    });



}

谢谢!

3 个答案:

答案 0 :(得分:1)

这里的问题是您在存储库中创建存储库代码,然后创建可变的实时数据的新对象并观察不同的对象`     接口回调{         onSuccess(字符串响应)         onError(字符串错误)     }

public void login(String username , String hashedPassword,Callback callback){
    final MutableLiveData<String> loggedInUser = new MutableLiveData<>();
    User user = new User(username,hashedPassword);

    usersRepositoryApi.login(user).enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            if (response.isSuccessful()) {
                callback.onSuccess(response.body());
            }
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            callback.onError(null);
        }
    });
}

//您的视图模型的登录方法`public void login(String userName,String hashedPassword){

    usersRepository.login(userName, hashedPassword,new Callback(){
       void onSuccess(String responsebody){
            loggedInUser.setValue(responsebody);
        }

        void onError(String error){
            loggedInUser.setValue(responsebody);
        }
    });
}                            

答案 1 :(得分:0)

在您的存储库中,尝试更改此部分:

loggedInUser.setValue(response.body());

到postValue函数。像这样:

loggedInUser.postValue(response.body());

答案 2 :(得分:0)

OP解决方案。

正如Neha Rathore所建议的那样,这是对我有用的解决方案:

在视图模型中:

public void login(String userName , String hashedPassword) {
    usersRepository.login(userName, hashedPassword, new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            loggedInUser.setValue(response.body());
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            loggedInUser.setValue(null);
        }
    });
}

以及在存储库中:

public void login(String username, String hashedPassword,@Nullable final Callback<String> callback){
    final MutableLiveData<String> loggedInUser = new MutableLiveData<>();
    User user = new User(username,hashedPassword);

    usersRepositoryApi.login(user).enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            if (response.isSuccessful()) {
                callback.onResponse(call,response);
            }
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            callback.onFailure(call,t);
        }
    });
}