//entity bean类
public class BaseResponseEntity {
public String code;//状态码:0,1
public String msg;
public T data;
}
public class User extends BaseResponseEntity {
public String mobile;
public String nickname;
public String age;
public String appkey;
public String appsecret;
public String createtime;
public String email;
public String fans;
public String follow;
public String gender;
public String icon;
public String latitude;
public String longitude;
public String money;
public String password;
public String praiseNum;
public String token;
public String uid;
public String userId;
public String username;
}
//utils 工具类
public class HttpConfig {
//retrofit根目录
public static final String _URL="http://120.27.23.105/";
}
------
/**
* Description:retrofit工具类
* 构造者模式如何封装:首先有各种builder过程,最后通过build()方法对对象进行创建
*/
public class RetrofitUtils {
//创建私有属性
private static RetrofitUtils mInstance;
//创建ApiService引用
private static ApiService apiService;
/**
* 声明私有构造方法,类似于单利模式,让调用者无法new出对象,只能通过构造者模式创建对象
*/
private RetrofitUtils() {
}
/**
* 先后调用的过程,只有对象给build成功之后,才能调用apiservice,这也是retrofit的几个先后的步骤
* @return
*/
public ApiService getApiService() {
return apiService;
}
public static class Builder {
private OkHttpClient okHttpClient;
private List callAdapterFactorys = new ArrayList<>();
private List convertFactorys = new ArrayList<>();
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactorys.add(factory);
return this;//返回this的目的是:可以链式调用
}
public Builder addConverterFactory(Converter.Factory factory) {
convertFactorys.add(factory);
return this;
}
public Builder client(OkHttpClient okHttpClient) {
this.okHttpClient = okHttpClient;
return this;
}
/**
* build方法才是真正的业务逻辑操作,才是真正构建对象的过程
* @return
*/
public RetrofitUtils build() {
Retrofit.Builder builder = new Retrofit.Builder();
if (convertFactorys != null && convertFactorys.size() == 0) {
//如果集合中没有对象,我们添加默认的gson解析器
builder.addConverterFactory(GsonConverterFactory.create());
}
for (Converter.Factory convertFactory : convertFactorys) {
builder.addConverterFactory(convertFactory);
}
if (callAdapterFactorys != null && callAdapterFactorys.size() == 0) {
builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
}
for (CallAdapter.Factory callAdapterFactory : callAdapterFactorys) {
builder.addCallAdapterFactory(callAdapterFactory);
}
//第一步创建retrofit对象
Retrofit retrofit = builder.client(okHttpClient).baseUrl(HttpConfig._URL)
.build();
//第二步,创建apiservice接口类
apiService = retrofit.create(ApiService.class);
//第三步,请求逻辑(这个供外部调用者调用)
mInstance = new RetrofitUtils();//私有构造方法,只有本类可以new出实例
return mInstance;
}
}
}
//ApiService
/**
* Description:retrofit接口方法,先从广度分包,再从深度细化功能类
* 实际在面试过程中,也是先从广度说起,再从深度挖掘,如果你刚开始就从深度挖掘,那么很容易挖的太深,给自己挖坑
*/
public interface ApiService {//接口类,只声明方法,不进行实现
//get请求
/*@GET("product/getProductDetail?source=android")
Observable rxjavaGoodDetails(@Query("pid") String pid);*/
@POST("user/reg")
@FormUrlEncoded Observable> rxjavaReg(@FieldMap Map params);
@POST("user/login")
@FormUrlEncoded Observable> rxjavaLogin(@FieldMap Map params);
}
//MVP模式
//Model
public class LoginModel {
/**
* 请求登录接口(登录接口的网络请求,实际上就是进行网络请求,拿到请求后的json字符串)
*
* @param mobile
* @param pass
*/
public void login(String mobile, String pass, final LoginCallback loginCallback) {
Map params = new HashMap<>();
params.put("mobile", mobile);
params.put("password", pass);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)//和okhttp关联,使用okhttp构造的一些功能,上面构建者模式,只构建了一个拦截器
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(HttpConfig._URL).build();
ApiService apiService = retrofit.create(ApiService.class);
apiService.rxjavaLogin(params).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(BaseResponseEntity value) {
//retrofit的观察者的四个回调方法,都是运行在主线程(okhttp的回调是运行在子线程)
if (value.code.equals("0")) {
loginCallback.loginSuccess(value);
} else {
//密码错误,手机号不存在等各种登录错误问题
loginCallback.loginFail(value);
}
}
@Override
public void onError(Throwable e) {
loginCallback.failure(e);
}
@Override
public void onComplete() {
}
});
}
public interface LoginCallback {
void loginSuccess(BaseResponseEntity user);//登录成功
void loginFail(BaseResponseEntity user);//登录失败
void failure(Throwable t);//网络请求失败
}
}
------
public class RegModel {
/**
* 请求登录接口(登录接口的网络请求,实际上就是进行网络请求,拿到请求后的json字符串)
*
* @param mobile
* @param pass
*/
public void reg(String mobile, String pass, final RegCallback regCallback) {
Map params = new HashMap<>();
params.put("mobile", mobile);
params.put("password", pass);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)//和okhttp关联,使用okhttp构造的一些功能,上面构建者模式,只构建了一个拦截器
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(HttpConfig._URL).build();
ApiService apiService = retrofit.create(ApiService.class);
apiService.rxjavaReg(params).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(BaseResponseEntity value) {
//retrofit的观察者的四个回调方法,都是运行在主线程(okhttp的回调是运行在子线程)
if (value.code.equals("0")) {
regCallback.regSuccess(value);
} else {
//密码错误,手机号不存在等各种登录错误问题
regCallback.regFail(value);
}
}
@Override
public void onError(Throwable e) {
regCallback.failure(e);
}
@Override
public void onComplete() {
}
});
}
public interface RegCallback {
void regSuccess(BaseResponseEntity user);//登录成功
void regFail(BaseResponseEntity user);//登录失败
void failure(Throwable t);//网络请求失败
}
}
---------------------------------------------
//Presenter
/**
* Description:控制器,逻辑层,需要连接model和view层
*/
public class LoginPresenter {
private LoginModel loginModel;
private ILoginView iLoginView;
public LoginPresenter(ILoginView iLoginView) {
loginModel = new LoginModel();
this.iLoginView = iLoginView;
}
/**
* 做本地校验逻辑的方法
*
* @param mobile
* @param pass 实际上校验本地的逻辑,需要一项非常重要的技术:正则表达式
*/
public void login(String mobile, String pass) {
if (mobile.length() == 0) {//手机号有自己的规则,比如11位,186开头,校验这些数据必须通过正则表达式
iLoginView.mobileError();
return;
}
if (TextUtils.isEmpty(pass.trim())) {//也就是输入框为空的时候
iLoginView.passError();
return;
}
//走model层,进行数据处理
loginModel.login(mobile, pass, new LoginModel.LoginCallback() {
@Override
public void loginSuccess(BaseResponseEntity user) {
iLoginView.loginSuccess(user);
}
@Override
public void loginFail(BaseResponseEntity user) {
iLoginView.loginFailure(user);
}
@Override
public void failure(Throwable t) {
iLoginView.failure(t);
}
});
}
}
-----
/**
* Description:控制器,逻辑层,需要连接model和view层
*/
public class RegPresenter {
private RegModel regModel;
private IRegView iRegView;
public RegPresenter(IRegView iRegView) {
regModel = new RegModel();
this.iRegView = iRegView;
}
/**
* 做本地校验逻辑的方法
*
* @param mobile
* @param pass 实际上校验本地的逻辑,需要一项非常重要的技术:正则表达式
*/
public void reg(String mobile, String pass) {
if (mobile.length() == 0) {//手机号有自己的规则,比如11位,186开头,校验这些数据必须通过正则表达式
iRegView.mobileError();
return;
}
if (TextUtils.isEmpty(pass.trim())) {//也就是输入框为空的时候
iRegView.passError();
return;
}
//走model层,进行数据处理
regModel.reg(mobile, pass, new RegModel.RegCallback() {
@Override
public void regSuccess(BaseResponseEntity user) {
iRegView.regSuccess(user);
}
@Override
public void regFail(BaseResponseEntity user) {
iRegView.regFailure(user);
}
@Override
public void failure(Throwable t) {
iRegView.failure(t);
}
});
}
}
-----------------------------------------
//View
public interface ILoginView {
void showProgressBar();//是否显示加载进度视图的方法
void mobileError();//手机号为空或者不合法
void passError();//密码为空或者不合法
void loginSuccess(BaseResponseEntity user);//网络请求成功,并且登录成功
void loginFailure(BaseResponseEntity user);//网络请求成功,但登录失败(有可能密码错误,有可能手机号错误)
void failure(Throwable t);//网络请求失败(断网,服务器崩溃,接口地址不正确,弱网)
}
------
public interface IRegView {
void showProgressBar();//是否显示加载进度视图的方法
void mobileError();//手机号为空或者不合法
void passError();//密码为空或者不合法
void regSuccess(BaseResponseEntity user);//网络请求成功,并且登录成功
void regFailure(BaseResponseEntity user);//网络请求成功,但登录失败(有可能密码错误,有可能手机号错误)
void failure(Throwable t);//网络请求失败(断网,服务器崩溃,接口地址不正确,弱网)
}
-----
public class MainActivity extends AppCompatActivity implements ILoginView,View.OnClickListener {
private LoginPresenter loginPresenter;
private EditText mMobileEt,mPwdEt;
private Button mLoginBtn,mRegisterBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
/**
* 初始化方法
*/
private void init() {
initView();
initData();
}
/**
* 初始化数据
*/
private void initData() {
loginPresenter = new LoginPresenter(this);
}
/**
* 初始化控件
*/
private void initView() {
mMobileEt = findViewById(R.id.mobile_et);
mPwdEt = findViewById(R.id.password_et);
mLoginBtn = findViewById(R.id.login_btn);
mRegisterBtn = findViewById(R.id.reg_btn);
mLoginBtn.setOnClickListener(this);
mRegisterBtn.setOnClickListener(this);
}
@Override
public void showProgressBar() {
}
@Override
public void mobileError() {
Toast.makeText(this, "手机号不能为空", Toast.LENGTH_SHORT).show();
}
@Override
public void passError() {
Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show();
}
@Override
public void loginSuccess(BaseResponseEntity user) {
Toast.makeText(this, user.msg, Toast.LENGTH_SHORT).show();
}
@Override
public void loginFailure(BaseResponseEntity user) {
Toast.makeText(this, user.msg, Toast.LENGTH_SHORT).show();
}
@Override
public void failure(Throwable t) {
System.out.println("failure:"+t);
}
@Override
public void onClick(View v) {
switch (v.getId()){
//点击登录按钮
case R.id.login_btn:
String mobile = mMobileEt.getText().toString();
String pass = mPwdEt.getEditableText().toString();
//需要通过控制器去处理逻辑
loginPresenter.login(mobile,pass);
break;
case R.id.reg_btn:
startActivity(new Intent(MainActivity.this,RegActivity.class));
break;
}
}
}
-----
public class RegActivity extends AppCompatActivity implements IRegView,View.OnClickListener {
private RegPresenter regPresenter;
private EditText mMobileEt,mPwdEt;
private Button mRegisterBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reg);
init();
}
/**
* 初始化方法
*/
private void init() {
initView();
initData();
}
/**
* 初始化数据
*/
private void initData() {
regPresenter = new RegPresenter(this);
}
/**
* 初始化控件
*/
private void initView() {
mMobileEt = findViewById(R.id.mobile_et);
mPwdEt = findViewById(R.id.password_et);
mRegisterBtn = findViewById(R.id.reg_btn);
mRegisterBtn.setOnClickListener(this);
}
@Override
public void showProgressBar() {
}
@Override
public void mobileError() {
Toast.makeText(this, "手机号不能为空", Toast.LENGTH_SHORT).show();
}
@Override
public void passError() {
Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show();
}
@Override
public void regSuccess(BaseResponseEntity user) {
Toast.makeText(this, user.msg, Toast.LENGTH_SHORT).show();
Log.d("有没有", user.msg);
}
@Override
public void regFailure(BaseResponseEntity user) {
Toast.makeText(this, user.msg, Toast.LENGTH_SHORT).show();
Log.d("有没有", user.msg);
}
@Override
public void failure(Throwable t) {
System.out.println("failure:"+t);
}
@Override
public void onClick(View v) {
String mobile = mMobileEt.getText().toString();
String pass = mPwdEt.getEditableText().toString();
//需要通过控制器去处理逻辑
regPresenter.reg(mobile,pass);
}
}
//依赖
compile 'io.reactivex.rxjava2:rxjava:2.0.1' //Rxjava
compile 'io.reactivex.rxjava2:rxandroid:2.0.1' //Rx安卓
compile 'com.squareup.retrofit2:retrofit:2.3.0' //Retrofit请求网络
compile 'com.squareup.retrofit2:converter-gson:2.3.0'//Gson
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.5.0'//拦截器
//权限