安卓自带LoginActivity解析

解析并通过安卓自带LoginActivity学习MVVM

谷歌官方提供了登陆界面,在搜索引擎找到的介绍都不尽如人意,大多是太高端,不适合初学者,于是在这里把这个代码解析一下,顺带学习一下MVVM框架,OK,开整!
首先我们右键创建一个LoginActivity,创建后的界面如下:
LoginActivity的界面
如图所示:直接生成了 dataui 两个Package。
为了便于理解,我们先从ui界面开始。看到哪里说到哪里,一步一步来。

1. LoginActivity

首先是LoginActivity,这个是全局的入口所在。
大道至简,两个输入框一个按钮
大道至简,两个输入框一个按钮。

主要功能放到了代码中,代码如下:

import  所有的库;//这里导入相应库,因为是自动生成,所以没必要每个库都解析一下

public class LoginActivity extends AppCompatActivity {
//这个将作为我们要讲的第一个点
    private LoginViewModel loginViewModel;   //vm,作用大概就是处理交互信息


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_login);   //这两句就是把界面和代码关联起来
        
        //新建VM
        loginViewModel = ViewModelProviders.of(this, new LoginViewModelFactory())
                .get(LoginViewModel.class);
		//找到组件
        final EditText usernameEditText = findViewById(R.id.username);  //用户名输入框
        final EditText passwordEditText = findViewById(R.id.password);  //密码输入框
        final Button loginButton = findViewById(R.id.login);
        final ProgressBar loadingProgressBar = findViewById(R.id.loading); //进度条/进度圈




        loginViewModel.getLoginFormState().observe(this, new Observer<LoginFormState>() {
            @Override
            public void onChanged(@Nullable LoginFormState loginFormState) {
                if (loginFormState == null) {
                    return;
                }
                loginButton.setEnabled(loginFormState.isDataValid());
                if (loginFormState.getUsernameError() != null) {
                    usernameEditText.setError(getString(loginFormState.getUsernameError()));
                }
                if (loginFormState.getPasswordError() != null) {
                    passwordEditText.setError(getString(loginFormState.getPasswordError()));
                }
            }
        });
/*监听改变状态获取user和password信息*/
        loginViewModel.getLoginResult().observe(this, new Observer<LoginResult>() {
            @Override
            public void onChanged(@Nullable LoginResult loginResult) {
                if (loginResult == null) {
                    return;
                }
                loadingProgressBar.setVisibility(View.GONE);
                if (loginResult.getError() != null) {
                    showLoginFailed(loginResult.getError());
                }
                if (loginResult.getSuccess() != null) {
                    updateUiWithUser(loginResult.getSuccess());
                }
                setResult(Activity.RESULT_OK);

                //Complete and destroy login activity once successful
                finish();
            }
        });
//对输入框的监听方法
        TextWatcher afterTextChangedListener = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                // ignore
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // ignore
            }

            @Override
            public void afterTextChanged(Editable s) {
                loginViewModel.loginDataChanged(usernameEditText.getText().toString(),
                        passwordEditText.getText().toString());
            }
        };
        /*给控件添加监听*/
        usernameEditText.addTextChangedListener(afterTextChangedListener);
        passwordEditText.addTextChangedListener(afterTextChangedListener);
        passwordEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
/*当在键盘上点击完成按钮之后*/
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_DONE) {
                    loginViewModel.login(usernameEditText.getText().toString(),
                            passwordEditText.getText().toString());
                }
                return false;
            }
        });
//给登录按钮添加监听
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadingProgressBar.setVisibility(View.VISIBLE);
                loginViewModel.login(usernameEditText.getText().toString(),
                        passwordEditText.getText().toString());
            }
        });
    }
/*更新UI*/
    private void updateUiWithUser(LoggedInUserView model) {
        String welcome = getString(R.string.welcome) + model.getDisplayName();
        // TODO : initiate successful logged in experience
        Toast.makeText(getApplicationContext(), welcome, Toast.LENGTH_LONG).show();
    }
//显示登陆失败
    private void showLoginFailed(@StringRes Integer errorString) {
        Toast.makeText(getApplicationContext(), errorString, Toast.LENGTH_SHORT).show();
    }
}

2. ViewModel
在一开始我们就创建了一个LoginViewModel,如果不知道是什么用处的话,接下来就没办法继续搞了,所以我们把LoginViewModel拿出来解析一下。

import 所有的库;//这里导入相应库,因为是自动生成,所以没必要每个库都解析一下

public class LoginViewModel extends ViewModel {

    private MutableLiveData<LoginFormState> loginFormState = new MutableLiveData<>();
    private MutableLiveData<LoginResult> loginResult = new MutableLiveData<>();
    private LoginRepository loginRepository;

    LoginViewModel(LoginRepository loginRepository) {
        this.loginRepository = loginRepository;
    }
//登录窗体的数据验证状态
    LiveData<LoginFormState> getLoginFormState() {
        return loginFormState;
    }
//登录结果,成功/失败信息
    LiveData<LoginResult> getLoginResult() {
        return loginResult;
    }
//登录,使用账号和密码登录
    public void login(String username, String password) {
        // can be launched in a separate asynchronous job
        Result<LoggedInUser> result = loginRepository.login(username, password);

        if (result instanceof Result.Success) {
            LoggedInUser data = ((Result.Success<LoggedInUser>) result).getData();
            loginResult.setValue(new LoginResult(new LoggedInUserView(data.getDisplayName())));
        } else {
            loginResult.setValue(new LoginResult(R.string.login_failed));
        }
    }
//输入信息改变之后
    public void loginDataChanged(String username, String password) {
        if (!isUserNameValid(username)) {
            loginFormState.setValue(new LoginFormState(R.string.invalid_username, null));
        } else if (!isPasswordValid(password)) {
            loginFormState.setValue(new LoginFormState(null, R.string.invalid_password));
        } else {
            loginFormState.setValue(new LoginFormState(true));
        }
    }

    // A placeholder username validation check
    //占位符用户名验证检查
    private boolean isUserNameValid(String username) {
        if (username == null) {
            return false;
        }
        if (username.contains("@")) {
            return Patterns.EMAIL_ADDRESS.matcher(username).matches();//这个方法是验证邮箱地址是否有效
        } else {
            return !username.trim().isEmpty();
        }
    }

    // A placeholder password validation check
    //占位符密码验证检查
    private boolean isPasswordValid(String password) {
        return password != null && password.trim().length() > 5;//不等于空并且长度大于5
    }
}

3.OK,有了View有了VM,按照我们MVVM的思维,我们还缺一个Model, 作为登录的Model,那么必然需要账号密码登陆状态等等等等的Model

既然是Model,那么应该放在data之下。我们接下来看第三个代码:LoggedInUser,找不到位置的请上翻到顶部。

/**
 * Data class that captures user information for logged in users retrieved from LoginRepository
 * 从LoginRepository检索到的已登录用户捕获用户信息的数据类
 */
public class LoggedInUser {

    private String userId;  //ID
    private String displayName;//名字

    public LoggedInUser(String userId, String displayName) {
        this.userId = userId;
        this.displayName = displayName;
    }

    public String getUserId() {
        return userId;
    }

    public String getDisplayName() {
        return displayName;
    }
}

很好理解不是吗…一个ID一个用户名。
——————————————————————————————————
在data之下还有三个代码,分别是:
LoginDataSource ------创建随机ID和一个用户名//代码里边是例子:用UUID作为ID,用“ Jane Doe”作为名字(提一嘴,JaneDoe 是“无名人士”的意思)。

LoginRepository------ 这个代码是 存储用户的,账户再次调用的时候可以用到。一般作为向服务器发送请求的参数。

Result----------登录结果,返回数据或者 登陆失败。

OK,Model我们看了,好像也没啥…

——————————————————————————
4.主要的东西已经学到了,我们看看剩下的ui里的几个文件:
LoggedInUserView--------------把用户信息显示到UI上
LoginFormState ----------- 主要写了三个属性:1.账号错误,2.密码错误 3.数据是否可用
LoginResult-------登录的结果:登录成功返回信息,或者登录失败返回int值
LoginViewModelFactory-------大概就是new了一个LoginViewModel。

以上是初学者个人对代码的解析,如果有大神看到了这篇文章并发现了不合理之处,请指正,非常感谢。

------本文章长期更新。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值