学习笔记Android+MVP+Retrofit登录案例

文章目录

    • 视图层接口
    • 视图层
    • 数据层接口
    • 数据层
    • 提供者
    • Retofit

Kotlin 改进版的看我的另一篇笔记 》》》》 点我点我

先看一下包结构
学习笔记Android+MVP+Retrofit登录案例_第1张图片

视图层接口

首先是View部分,此部分管理整个模块的视图操作,按照需求先定义一下接口

public interface ILoginView {
    //得到用户填写的信息
    String getUsername();

    String getPassword();

    //显示和隐藏登录dialog
    void showDialog();

    void hideDialog();

    void showToast(String t);

    //登录成功后,返回的方法
    void onSuccess();

    void clearUsername();

    void clearPassword();

    void setUsernameError(String s);

    void setPasswordError(String s);

}

视图层

在activity中实现ILoginView

public class LoginActivity extends BaseActivity implements ILoginView {

    @BindView(R.id.et_username)
    EditText etUsername;
    @BindView(R.id.et_password)
    EditText etPassword;
    @BindView(R.id.forget_password)
    TextView forgetPassword;
    private LoginPresenter presenter;

    @Override
    protected int getContentView() {
        return R.layout.activity_login;
    }

    @Override
    protected void init() {
        presenter = new LoginPresenter(this);
        //回车键登陆
        etPassword.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
                if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
                    presenter.login();
                    return true;
                }
                return false;
            }
        });
    }

    @OnClick({R.id.forget_password, R.id.sign_in_button})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.forget_password:
                break;
            case R.id.sign_in_button:
                presenter.login();
                break;
        }
    }

    @Override
    public String getUsername() {
        return etUsername.getText().toString().trim();
    }

    @Override
    public String getPassword() {
        return etPassword.getText().toString().trim();
    }

    @Override
    public void showDialog() {
        showLoading();
    }

    @Override
    public void hideDialog() {
        hideLoading();
    }

    @Override
    public void showToast(String t) {
        ToastUtils.showToast(t);
    }

    @Override
    public void onSuccess() {
        removeAll();//关闭所有activity
        goToActivity(MainActivity.class);//前往主页面(这两个方法是baseactivity里定义的)
    }

    @Override
    public void clearUsername() {
        etUsername.setText("");
    }

    @Override
    public void clearPassword() {
        etPassword.setText("");
    }

    @Override
    public void setUsernameError(String s) {
        etUsername.setError(s);
        etUsername.requestFocus();
    }

    @Override
    public void setPasswordError(String s) {
        etPassword.setError(s);
        etPassword.requestFocus();
    }

}

我的BaseActivity,酌情取用

public abstract class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getContentView());
        ButterKnife.bind(this);
        init();
    }

    protected abstract int getContentView();

    protected abstract void init();

    //启动新的activity
    public void goToActivity(Class Activity) {
        Intent intent = new Intent(this, Activity);
        startActivity(intent);
    }

    public void showLoading() {
        LoadingUtils.instance.ShowLoading(this);
    }

    public void hideLoading() {
        LoadingUtils.instance.DismissLoading();
    }

}

数据层接口

model部分用来提供整个模块的数据
下面是model的接口

public interface ILoginModel {
    void login(String username, String password, LoginCallback loginCallback);

    interface LoginCallback {

        void Success(User user);

        void Failed(String s);
    }
}

数据层

model实现类

public class LoginModel implements ILoginModel {

    @Override
    public void login(final String username, final String password, final LoginCallback loginCallback) {

        NetClient.instance.login(username, MD5Util.md5(password)).enqueue(new Callback<BaseResponse<User>>() {
            @Override
            public void onResponse(Call<BaseResponse<User>> call, Response<BaseResponse<User>> response) {
                if (response.body() != null) {
                    if (response.body().isSuccess()) {
                        User user = response.body().getRows().get(0);
                        loginCallback.Success(user);
                    } else {
                        loginCallback.Failed(response.body().getMsg());
                    }
                } else {
                    loginCallback.Failed("获取数据失败");
                }
            }

            @Override
            public void onFailure(Call<BaseResponse<User>> call, Throwable t) {
                loginCallback.Failed(t.getMessage());
            }
        });
    }
}

然后就是presenter部分,处理整个模块的逻辑

提供者

public class LoginPresenter {
    private ILoginModel model;
    private ILoginView view;

    LoginPresenter(ILoginView view) {
        this.view = view;
        model = new LoginModel();
    }

    public void login() {
        view.showDialog();
        if (checkData(view.getUsername(), view.getPassword())) {
            model.login(view.getUsername(), view.getPassword(), new ILoginModel.LoginCallback() {
                @Override
                public void Success(User user) {
                    if (user.getUserName() != null) {
                        UserUtils.saveUser(user);
                        view.showToast("登录成功!");
                        view.onSuccess();
                    } else {
                        view.clearUsername();
                        view.clearPassword();
                        view.setUsernameError("用户名或密码错误");
                    }
                    view.hideDialog();
                }

                @Override
                public void Failed(String s) {
                    view.showToast(s);
                    view.hideDialog();
                }
            });
        } else {
            view.hideDialog();
        }
    }

    private boolean checkData(String username, String password) {
        view.setUsernameError(null);
        view.setPasswordError(null);
        if (TextUtils.isEmpty(username)) {
            view.setUsernameError("请输入账号");
        } else if (TextUtils.isEmpty(password)) {
            view.setPasswordError("请输入密码");
        } else if (!isPasswordValid(password)) {
            view.clearPassword();
            view.setPasswordError("密码太短了");
        } else if (!isUserNameValid(username)) {
            view.clearUsername();
            view.setUsernameError("账号格式不对");
        } else {
            return true;
        }
        return false;
    }
	//下面是用户名和密码的要求,根据自己需要设定
    private boolean isUserNameValid(String username) {
        return username.length() == 11;
    }

    private boolean isPasswordValid(String password) {
        return password.length() > 5;
    }
}

Retofit

最后简单带一下我自己的retrofit的用法

这里写图片描述

先加一下依赖

    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'//数据解析
    implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'//打印日志

定义一下项目的联网访问接口,都可以放在这里统一管理

public interface NetService {
    //登录
    @FormUrlEncoded
    @POST("UserAction/login")
    Call<BaseResponse<User>> login(
            @Field("username") String username, 
            @Field("password") String password
    );
    ...其它接口
}

最后用单例模式写个client
采用了枚举类实现单例

public enum NetClient {

    instance;

    private static final String BASE_URL = "http://192.168.0.1:8080/项目名/";//服务器项目地址
    private NetService service;

    NetClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (BuildConfig.DEBUG) {
            // Log信息拦截器
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//这里可以选择拦截级别
            //设置 Debug Log 模式
            builder.addInterceptor(loggingInterceptor);
        }
        OkHttpClient client = builder.build();
        service = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build()
                .create(NetService.class);
    }
	//登录
    public Call<BaseResponse<User>> login(String username, String password) {
        return service.login(username, password);
    }
    ...其它联网操作

然后就可以在model里调用啦~( ̄▽ ̄~),见上方model部分(^ _ ^)/~~

你可能感兴趣的:(学习笔记)