简体   繁体   English

重新加载片段后触发 LiveData 观察者

[英]LiveData observer triggered after reloading fragment

My MainAcivity hosts 2 fragments, login and register.我的 MainAcivity 托管 2 个片段,登录和注册。 I have a LiveData observer on LoginFragment that observes user login live data, after which if user is authenticated MainMenuActivity intent will start.我在 LoginFragment 上有一个 LiveData 观察者,它观察用户登录实时数据,之后如果用户通过身份验证,MainMenuActivity 意图将启动。 On main menu there's logout button that would start MainActivity and load LoginFragment.在主菜单上有一个注销按钮,它将启动 MainActivity 并加载 LoginFragment。

But here's the problem, the observer on LoginFragment triggered immediately after loading the fragment, which straight up start MainMenuActivity intent again.但问题是,LoginFragment 上的观察者在加载片段后立即触发,直接启动 MainMenuActivity 意图。

My LoginFragment:我的登录片段:

public class LoginFragment extends Fragment {
    public static LoginFragment newInstance(){
        return new LoginFragment();
    }

    private LoginViewModel mLoginViewModel;
    private LiveData<UserModelJSONPlaceholder> mUserModelLiveData;

    private static final String TAG = "FragLogin";
    private Button mBtnLogin;
    private EditText mTxtUsername, mTxtPass;
    private TextView mTxtRegister;
    private CheckBox mCheckBoxRemember;
    private TextView mTxtInvalid;
    private Callbacks mCallbacks = null;
    private ProgressBar mProgressBar;
    private UserApiInterface mAPIInterface;
    private SharedPreferences mSharedPreferences;
    private SharedPreferences.Editor mPreferencesEditor;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_login,container,false);

        mBtnLogin = view.findViewById(R.id.btnLogin_login);
        mTxtUsername = view.findViewById(R.id.txtUsername);
        mTxtPass = view.findViewById(R.id.txtPass);
        mCheckBoxRemember = view.findViewById(R.id.checkBoxRememberMe);
        mTxtRegister = view.findViewById(R.id.txtRegister_login);
        mProgressBar = view.findViewById(R.id.progressBar);
        mTxtInvalid = view.findViewById(R.id.txtInvalid);

        mProgressBar.setVisibility(View.GONE);
        mTxtInvalid.setVisibility(View.GONE);

        mAPIInterface = APIClient.getClient().create(UserApiInterface.class);
        mSharedPreferences = getContext().getSharedPreferences("login",Context.MODE_PRIVATE);
        mPreferencesEditor = mSharedPreferences.edit();
        setListener();

        return view;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mLoginViewModel = new ViewModelProvider(this).get(LoginViewModel.class);

        mUserModelLiveData = mLoginViewModel.getUserModelLiveData();

        //observer would be triggered right after loading fragment after logout
        mUserModelLiveData.observe(this, new Observer<UserModelJSONPlaceholder>() {
            @Override
            public void onChanged(UserModelJSONPlaceholder userModel) {

                Log.d(TAG, "onChanged: Observer: "+userModel.getResponse());
                mProgressBar.setVisibility(View.GONE);
                String loginAuth = userModel.getResponse();

                if(loginAuth.equals("OK")){
                    mPreferencesEditor.putString("name",userModel.getUserModel().getName());
                    mCallbacks.login_goMainMenu(userModel.getUserModel().getName());
                }else{
                    mTxtInvalid.setVisibility(View.VISIBLE);
                }
            }
        });
    }

    private void doLogin(){
        mProgressBar.setVisibility(View.VISIBLE);
        final String username = mTxtUsername.getText().toString().trim();
        final String password = mTxtPass.getText().toString().trim();
        mLoginViewModel.authLogin(username,password);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mCallbacks = (Callbacks) context;
    }

    private void setListener(){
        mBtnLogin.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                doLogin();
            }
        });
        mTxtRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCallbacks.login_goRegister();
            }
        });
        mCheckBoxRemember.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(buttonView.isChecked()){
                    mPreferencesEditor.putBoolean("rememberMe", true).apply();
                    Log.d(TAG, "onCheckedChanged: Checked");
                }else{
                    mPreferencesEditor.putBoolean("rememberMe", false).apply();
                    Log.d(TAG, "onCheckedChanged: Unchecked");
                }
            }
        });
    }

    public interface Callbacks{
        void login_goMainMenu(String name);
        void login_goRegister();
    }
}

My MainMenuActivity:我的 MainMenuActivity:

public class MainMenuActivity extends AppCompatActivity {
    private static final String ARG_NAME = "arg_name";

    private Button mBtnEnterQ,mBtnCreateQ;
    private TextView mTxtName;
    private Toolbar mToolbar;
    private SharedPreferences mSharedPreferences;
    private SharedPreferences.Editor mEditor;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_menu);

        mBtnEnterQ = findViewById(R.id.btnEnterQ);
        mBtnCreateQ = findViewById(R.id.btnCreateQ);
        mTxtName = findViewById(R.id.txtUsername);
        mToolbar = findViewById(R.id.toolbar);
        mSharedPreferences = getSharedPreferences("login",MODE_PRIVATE);
        mEditor = mSharedPreferences.edit();

        setSupportActionBar(mToolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar_menu,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case R.id.itemLogout:
                doLogout();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void doLogout(){
        mEditor.remove("rememberMe");
        mEditor.apply();
        Intent i = new Intent(this, MainActivity.class);
        startActivity(i);
        finish();
    }
}

and here's my ViewModel and Repo for LoginFragment:这是我用于 LoginFragment 的 ViewModel 和 Repo:

public class LoginViewModel extends ViewModel {
    private static final String TAG = "LoginVM";
    private UserRepository mUserRepository;
    LiveData<UserModelJSONPlaceholder> mUserModelLiveData;


    public LoginViewModel() {
        mUserRepository = UserRepository.getInstance();
    }

    public void authLogin(String username, String password){
       mUserRepository.authLogin(username,password);
    }

    public LiveData<UserModelJSONPlaceholder> getUserModelLiveData() {
        return mUserRepository.getUserModelLiveData();
    }
}

public class UserRepository {
    private static UserRepository instance;

    private static final String TAG = "RepoUser";
    private UserApiInterface mUserApiInterface;
    MutableLiveData<UserModelJSONPlaceholder> userModelLiveData;

    public static UserRepository getInstance(){
        if(instance==null){
            instance=new UserRepository();
        }
        return instance;
    }

    private UserRepository(){
        mUserApiInterface = APIClient.getClient().create(UserApiInterface.class);
        Log.d(TAG, "UserRepository: repoInit");
    }

    public void authLogin(String username, String password){
        Log.d(TAG, "authLogin: REQUEST INIT");
        Log.d(TAG, "authLogin: SERVER: "+ CONFIG.SERVER);
        mUserApiInterface.getUser(username,password).enqueue(new Callback<UserModelJSONPlaceholder>() {
            @Override
            public void onResponse(Call<UserModelJSONPlaceholder> call, Response<UserModelJSONPlaceholder> response) {
                if(response.isSuccessful()){
                    UserModelJSONPlaceholder r = response.body();
                    userModelLiveData.postValue(response.body());
                }else{
                    Log.d(TAG, "onResponse: FAILED. "+response.errorBody());
                }
            }

            @Override
            public void onFailure(Call<UserModelJSONPlaceholder> call, Throwable t) {
                Log.d(TAG, "onFailure: "+t.getMessage());
            }
        });
    }

    public LiveData<UserModelJSONPlaceholder> getUserModelLiveData() {
        if(userModelLiveData == null)
            userModelLiveData = new MutableLiveData<>();

        return userModelLiveData;
    }
}

Your problems is you make UserRepository is Singleton instance and always keep value of userModelLiveData easy way to fix it change method to this您的问题是您将UserRepository为 Singleton 实例,并始终保持userModelLiveData的值,轻松修复它的方法更改为此

public LiveData<UserModelJSONPlaceholder> getUserModelLiveData() {
        userModelLiveData = new MutableLiveData<>();
        return userModelLiveData;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM