网络新宠:基于MVP由okhttp衍生的Retrofit网络新框架
引言
最近一直研究现在最时新的网络请求框架,然而最吸引眼球的自然是Retrofit,别具一格的注解请求接口,封装好的get,post请求让开发者省了不少时间,也让代码显得简洁,耦合性自然低了很多。另外结合比较火的MVP开发模式,再一次大强度的提高了代码复用性,绝对的降低代码的耦合性。现在我把二者整合的一套完整框架分享出来,仅供参考。
首先是导包,以下是我导入到gradle中的一些资源包
dependencies {//必须导入okhttp包,retrofit本身起源于okhttp,另外用于post请求的Gson、fastJson转码方式任选一种,为了方便,我这里都导入了。
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.squareup.okhttp:okhttp:2.7.0'
compile 'com.google.code.gson:gson:2.2.4'
compile 'com.github.bumptech.glide:glide:3.6.1'
compile 'com.alibaba:fastjson:1.2.12'
compile 'com.google.android.gms:play-services-appindexing:8.1.0'
// -------------------- 以下三个库是必须依赖的 ----------------------------
compile 'cn.bingoogolapple:bga-banner:2.0.4@aar'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.nineoldandroids:library:2.4.0'
// -------------------- 以上三个库是必须依赖的 ----------------------------
// 以下几个库是演示案例所使用到的
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
// compile project(':bannerlibrary')
}
通过查看Retrofit源码,我们知道构建Retrofit框架之前,必须要用到格式工厂,请求的域名,以及请求接口处用到的公共头header(没有可不加),于是我对以上三点进行了简单封装。
public class RetrofitAPIManager {
public static final String SERVER_URL = "服务器域名";
public static Engine provideClientApi() {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())//格式工厂
.baseUrl(SERVER_URL)//域名
.client(genericClient())//公共请求头
.build();
return retrofit.create(Engine.class);
}
public static OkHttpClient genericClient() {
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("platform", "2")
.addHeader("appBuildVersion", "14")
.addHeader("tokenId", LoginPresenter.lf==null?"":LoginPresenter.lf.getToken())
.build();
return chain.proceed(request);
}
}).build();
return httpClient;
}
}
大前提准备完毕,下面创建所需要的接口,这是我创建的几个基本接口,仅供参考。
public interface Engine {
/*
首页Banner
*/
@GET("index.htm")
Call<HomepageBean> homepager_banner();
/*
活动列表
*/
@GET("advertisement/promotionList.htm")
Call<PromotionListBean> promotionlist();
/*
个人中心
*/
@GET("searchUserInfo.htm")
Call<PromotionListBean> UserInfo();
/*
登录
*/
@FormUrlEncoded
@POST("userLogin/login.htm")
Call<LoginBean> Login(@Field("data") String data);
}
以上Retrofit就已经搭建完成了,下面我们以MVP模式为导图进行下一步编码,MVP主要是为了把View与Model分开管理从而降低耦合性,提高代码复用性。明白这一点,于是开始搭建model与view最后用一个presenter把二者结合起来实现界面功能。
这里以一个用户登录记录Token的操作为例实现post请求,首先建立model
public interface LoginModel {//参数为我需要传给服务器的用户名,密码以及其他一些信息
void loadLogin(String mobile, String password, String type, String partytype, String openid, LoginModelImpl.OnLoadLoginListener listener);
}
建立一个实现类去实现model方法
public class LoginModelImpl implements LoginModel {
@Override
public void loadLogin(String mobile, String password, String type, String partytype, String openid, final OnLoadLoginListener listener) {
Map<String, String> map = new HashMap<>();
map.put("mobile", mobile);
map.put("password", password);
map.put("loginType", type);
map.put("thirdPartyType", partytype);
map.put("thirdPartyOpenId", openid);
String param = JSON.toJSONString(map, true);//因为是post请求,这里将参数转成json格式
MainActivity.mEngine.Login(param).enqueue(new Callback<LoginBean>() {
//利用Engine整合的接口,进行Retrofit请求
@Override
public void onResponse(Call<LoginBean> call, Response<LoginBean> response) {
LoginBean bean = response.body();
if (bean.getResult().equals("1")) {
listener.onSuccess(bean);
}
}
@Override
public void onFailure(Call<LoginBean> call, Throwable t) {
listener.onFailure(t.getMessage());
}
});
}
public interface OnLoadLoginListener {//回调接口,整合presenter时调用
void onSuccess(LoginBean newsDetailBean);
void onFailure(String msg);
}
}
model建立完毕,其次建立view,想到一个用户登录,请求时会有进度条的展示,于是建立View接口
public interface LoginView {
void showProgress();
void hideProgress();
}
最重要的步骤来了,现在把model与view整合到presenter中,实现界面操作。
public class LoginPresenter implements LoginModelImpl.OnLoadLoginListener{
private LoginModel loginModel;
private LoginView loginView;
private Context mContext;
public static LoginRoleInformation lf;
public LoginPresenter(LoginView loginView,Context mContex) {
this.loginView = loginView;
this.mContext = mContex;
loginModel = new LoginModelImpl();
lf = new LoginRoleInformation(mContex);
}
public void loadPresenter(String mobile, String password, String type, String partytype, String openid){
loginView.showProgress();
loginModel.loadLogin(mobile,password,type,partytype,openid,this);
}
//回调中跟新UI以及数据处理
@Override
public void onSuccess(LoginBean bean) {
loginView.hideProgress();
HttpRequest.initToast(mContext,bean.getMessage());
lf.setLoginInfo(bean.getData().getMobile(),bean.getData().getPassword(),bean.getToken(),bean.getData().getIsIdentity(), bean.getData().getIsBindBankcard(), bean.getData().getIsSetPayPassword(),bean.getData().getId());//记录token
}
@Override
public void onFailure(String msg) {
loginView.hideProgress();
HttpRequest.initToast(mContext,msg);
}
}
最后将presenter整合到LoginActivity中,实现功能。
/**
* @author admin 登录
*/
public class loginActivity extends Activity implements LoginView{
private EditText user, pass;
private Button bt;
private ProgressBar progressBar;
private LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
user = (EditText) findViewById(R.id.user);
pass = (EditText) findViewById(R.id.pass);
bt = (Button) findViewById(R.id.bt_login);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
loginPresenter = new LoginPresenter(this,this);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//presenter中整合的方法,这里我只传进去一个用户名和密码
loginPresenter.loadPresenter(user.getText().toString(),pass.getText().toString(),"","","");
});
}
@Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
}
布局文件就不贴了 主要是一个用户名输入框和一个密码输入框加一个登录按钮。到此,我们的功能就基本实现了,点击登录按钮,显示进度条,记录token,请求结束隐藏进度条。主要演示了retrofit的post请求方式以及MVP开发模式的部署。谢谢观看。