是的,最近又在写Android,不要问我为什么,心累。
Retrofit2 可以极大的简便网络交互,从此不用自己去管理线程,建立handler之类的。
Retrofit2 的使用主要包括三个部分:
- 定义网络交互接口
- 定义解析返回结果类
- 在上面两个的基础上进行使用
我前面看了一些资料,但是感觉不够直观(目的和过程不够清晰,其他都挺好的,官方链接:https://github.com/square/retrofit/blob/master/samples/src/main/java/com/example/retrofit/SimpleService.java。和rxjava一起使用: https://blog.csdn.net/pgg_cold/article/details/79116424)
本文以登录为例:
接口:http://ip地址/user/login/
参数:name, password
返回类似json格式,如:{"code":"2", "msg":"error"}
根据需求定义网络交互和实体类,这里处于方便写在了一起, 仅以post方式为例:
提示:BASE_URL 必须以“/”结尾, 与@POST(“接口”) 构成完整的请求地址。
Call 决定了你的解析类型(支持配置Gson等解析,一句话完成),ResponseBody
public class LoginService {
public static final String BASE_URL = "http://ip地址/";
/**
* 登录交互接口
* post方式提交请求,表单方式配合Field或FieldMap提供参数,返回JavaBean或者ResponseBody
*/
public interface Login{
@POST("user/login")
@FormUrlEncoded
Call<LoginBean> loginCode(@Field("name") String user, @Field("password") String passswd);
// Call<LoginBean> loginCode(@FieldMap Map<String, Object> map); // Map方式。仅仅是在调用时参数写法的差异
}
/**
* 数据返回实体
*/
public class LoginBean{
private String code;
private String msg;
public LoginBean(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
}
点击登录事件:
mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
'''
doLogin(); // 登录
}
}
});
登录方法实现:
/**
* 网络登录请求
* @return
*/
public void doLogin(){
// 创建Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(LoginService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) // Gson解析
.build();
// 创建网络请求接口的实例
LoginService.Login login = retrofit.create(LoginService.Login.class);
// 通过接口实例发送请求并获取返回值
// 这里直接传值就可以了,使用FieldMap的话要新建一个Map对象并赋值
Call<LoginService.LoginBean> call = login.loginCode(mUser, mPasswd);
// 处理返回结果
call.enqueue(new Callback<LoginService.LoginBean>() {
@Override
public void onResponse(Call<LoginService.LoginBean> call, Response<LoginService.LoginBean> response) {
// 通过配置了GsonConverterFactory可以很方便的通过get方法获取对应的值
if (response.body().getCode().equals("1")){
Intent intent = new Intent(mContext, MainActivity.class);
//startActivity(intent);
}else {
Toast.makeText(mContext, response.body().getMsg(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<LoginService.LoginBean> call, Throwable t) {
Toast.makeText(mContext, "请检查网络连接", Toast.LENGTH_SHORT).show();
}
});
}
怎么样,还挺方便的吧,解析多个对象(如 List)应该也是可以的,或者参考官方链接。其他请求方式后面可能会写也可能不会写。
Activity完整代码:
package com.example.iot.activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.example.iot.R;
import com.example.iot.service.LoginService;
import com.example.iot.utils.Constant;
import com.example.iot.view.ClearEditText;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class LoginActivity extends AppCompatActivity {
private static String TAG = "---LoginActivity---";
// 控件
private ClearEditText mEditUser;
private ClearEditText mEditPasswd;
private Button mBtnLogin;
// 数据
private Context mContext;
private String mUser = "";
private String mPasswd = "";
private SharedPreferences pref;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// 数据
mContext = this;
pref = getSharedPreferences("user", MODE_PRIVATE);
// 绑定控件
mEditUser = findViewById(R.id.etUser);
mEditPasswd = findViewById(R.id.etPasswd);
mBtnLogin = findViewById(R.id.btnLogin);
// 是否填充数据
if(! pref.getAll().isEmpty()){
mUser = pref.getString("user", "");
mPasswd = pref.getString("passwd", "");
mEditUser.setText(mUser);
mEditPasswd.setText(mPasswd);
}
mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mUser = mEditUser.getText().toString();
mPasswd = mEditPasswd.getText().toString();
if (mUser.length()<1 || mPasswd.length()<1){
Toast.makeText(mContext, "用户名或密码为空", Toast.LENGTH_SHORT).show();
}else {
SharedPreferences.Editor editor = pref.edit();
editor.putString("user", mUser);
editor.putString("passwd", mPasswd);
editor.commit();
doLogin(); // 登录
}
}
});
}
/**
* 网络登录请求
* @return
*/
public void doLogin(){
// 创建Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(LoginService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// 创建网络请求接口的实例
LoginService.Login login = retrofit.create(LoginService.Login.class);
// 通过接口实例发送请求并获取返回值
Call<LoginService.LoginBean> call = login.loginCode(mUser, mPasswd);
// 处理返回结果
call.enqueue(new Callback<LoginService.LoginBean>() {
@Override
public void onResponse(Call<LoginService.LoginBean> call, Response<LoginService.LoginBean> response) {
if (response.body().getCode().equals("200")){
Intent intent = new Intent(mContext, MainActivity.class);
//startActivity(intent);
}else {
Toast.makeText(mContext, response.body().getMsg(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<LoginService.LoginBean> call, Throwable t) {
Toast.makeText(mContext, "请检查网络连接", Toast.LENGTH_SHORT).show();
}
});
}
}