介绍
常用的网络请求方法
@GET
使用@Query单个参数 @QueryMap多个参数
@POST
使用@Field 单个参数 @FieldMap 多个参数 @Part 上传文件 @PartMap 上传多个文件
总体使用步骤:
1.添加Retrofit依赖库
2.创建接受服务器返回数据的类
3.创建用于描述网络请求的接口
4.创建Rerofit实例
5.创建网络请求接口实例
6.发送网络请求(异步和同步)
7.处理返回数据
8.进阶理解从复杂到精简的过程
9.上传文件使用
使用
当你想要做任何网络请求的操作时,一定要提前首先加上网络权限,这是很多新手容易忘记的通病,以前我也老忘哈哈。。。。。
下面来看具体使用方法:
1.导入依赖包
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.google.code.gson:gson:2.2.4'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
2.创建Bean类
http://v.juhe.cn/toutiao/index?key=d05b58fa6901ad9bed77a1ef08bd6ccb 为了方便给你们提供了一下url地址,仅供学习使用
用gson 快捷方式,生成一个数据类,这个大家都会把,如果不会的话百度搜gosn 插件即可
3.创建存放网络请求的接口
//{name}是一个替换块,搭配@Path("name")动态传参数
public interface PostService{
@GET("{name}/index?key=d05b58fa6901ad9bed77a1ef08bd6ccb")
Call<Getbean> getString(@Path("name") String name);
}
4..创建并初始化Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://v.juhe.cn/")//设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
.build();
5.连接网络请求接口调用其方法
GetService service = retrofit.create(GetService.class);
Call<GetBean> call = service.getString3("toutiao");
6.同步和异步请求方式
//同步操作,必须开启子线程
new Thread(new Runnable() {
@Override
public void run() {
try {
Response<GetBean> execute = call.execute();
GetBean bean = execute.body();
Message msg=hand.obtainMessage();
msg.obj=bean.toString();
msg.what=102;
hand.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
//异步操作
call.enqueue(new Callback<GetBean>() {
@Override
public void onResponse(Call<GetBean> call, Response<GetBean> response) {
GetBean bean = response.body();
Log.e("zhoukang", "" + bean.toString());
}
@Override
public void onFailure(Call<GetBean> call, Throwable t) {
}
});
7.处理返回数据
Handler hand=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//TODO 处理逻辑
}
};
8.进阶理解从复杂到精简的过程
- GET 请求方式
//直接拼接,记得加问号
@GET("toutiao/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb")
Call<GetBean> getString();
//{name}可以最简单的将其理解为路径替换块,用”{}”表示,与注解@path配合使用 ,为了解耦,参数name==toutiao
@GET("{name}/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb")
Call<GetBean> getString2(@Path("name") String name);
//对于@GET来说,参数信息是可以直接放在url中上传的。那么你马上就反应过来了,这一样也存在严重的耦合!
//于是,就有了@query
@GET("{name}/index")
Call<GetBean> getString3(@Path("name")String name,@Query("type") String type
,@Query("key") String key);
//假设我要在参数中上传10个参数呢?这意味着我要在方法中声明10个@Query参数?当然不是!
//Retrofit也考虑到了这点,所以针对于复杂的参数上传,为我们准备了@QueryMap
@GET("{name}/index")
Call<GetBean> getString4(@Path("name") String name, @QueryMap HashMap<String,String> hashMap);
- Post方式
//注意:千万别忘了标记 @FormUrlEncoded
@FormUrlEncoded
@POST("toutiao/index")
Call<PostBean> postString(@Field("type") String type, @Field("key") String key);
// Post表单提交-多个参数-@FieldMa
@FormUrlEncoded
@POST("toutiao/index")
Call<PostBean> postString2(@FieldMap HashMap<String,String> params);
- MainActivity文件
/**
*
*/
public class MainActivity extends AppCompatActivity {
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = findViewById(R.id.tv);
// initGet();
try {
initPost();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private void initPost() throws UnsupportedEncodingException {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://v.juhe.cn/")
.addConverterFactory(GsonConverterFactory.create())
.build();
PostService service = retrofit.create(PostService.class);
//解决中文乱码,服务器后台不认识造成数据为响应
String name = URLEncoder.encode("社会", "UTF-8");
HashMap<String, String> map = new HashMap<>();
map.put("type", name);
map.put("key", "d05b58fa6901ad9bed77a1ef08bd6ccb");
Call<PostBean> call = service.postString2(map);
call.enqueue(new Callback<PostBean>() {
@Override
public void onResponse(Call<PostBean> call, Response<PostBean> response) {
if (response.isSuccessful()) {
PostBean bean = response.body();
Message msg = hand.obtainMessage();
msg.obj = bean.toString();
msg.what = 102;
hand.sendMessage(msg);
Log.e("zhoukang", "" + bean.toString());
}
}
@Override
public void onFailure(Call<PostBean> call, Throwable t) {
Log.e("zhoukang", "R1++ 失败" + t.getMessage());
}
});
}
private void initGet() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://v.juhe.cn/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GetService service = retrofit.create(GetService.class);
final Call<GetBean> call = service.getString3("toutiao", "shehui", "d05b58fa6901ad9bed77a1ef08bd6ccb");
//异步请求操作
new Thread(new Runnable() {
@Override
public void run() {
try {
Response<GetBean> execute = call.execute();
GetBean bean = execute.body();
Message msg = hand.obtainMessage();
msg.obj = bean.toString();
msg.what = 102;
hand.sendMessage(msg);
Log.e("zhoukang", "" + bean.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
Handler hand = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//TODO 处理逻辑
if (msg.what == 102) {
String result = (String) msg.obj;
mTv.setText(result);
}
}
};
}
9.图片文件上传
无聊自己写了一个工具类,可以进行扩展使用
public class RetrofitHelper {
Retrofit retrofit = null;
String BASEURL = "接口地址";
private final PostService mService;
public static RetrofitHelper retrofitHelper = new RetrofitHelper();
private RetrofitHelper() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASEURL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
//通过retrofit类去把我们的网络请求service实例化出来
mService = retrofit.create(PostService.class);
}
public static RetrofitHelper getInstance() {
return retrofitHelper;
}
//提供一些方法去调用service实体类的方法,RequestBody上传单个文件
public void uploadFile(RequestBody body, final OnSuccessListener listener) {
Call<TestBean> call = mService.postFile(body, "");
call.enqueue(new Callback<TestBean>() {
@Override
public void onResponse(Call<TestBean> call, Response<TestBean> response) {
listener.onSuccess(response);
}
@Override
public void onFailure(Call<TestBean> call, Throwable t) {
listener.onFaile();
}
});
}
//提供一些方法去调用service实体类的方法,HashMap上传多个文件
public void uploadFile2(HashMap<String, RequestBody> map, final OnSuccessListener listener) {
Call<TestBean> call = mService.postFile2(map, "");
call.enqueue(new Callback<TestBean>() {
@Override
public void onResponse(Call<TestBean> call, Response<TestBean> response) {
listener.onSuccess(response);
}
@Override
public void onFailure(Call<TestBean> call, Throwable t) {
listener.onFaile();
}
});
}
//当我获取数据成功后要做什么处理
public interface OnSuccessListener {
void onSuccess(Object o);
void onFaile();
}
}
MainAtivity.java
/**
* 单张图片上传
*
* @throws IOException
*/
private void initUpateBitmap() {
//获取图片路径,这只是个简单的例子,项目开发中会有很多图片需要上传,一般从相册和相机里获取,并且保存到后台服务器时必须自己定义名字
// ,这样就不会发生图片替换(原因名字重复)
File file = new File(Environment.getExternalStorageDirectory() + "/" + "retrofit/" + "ceshi.jpg");
RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file);
RetrofitHelper.getInstance().uploadFile(body, new RetrofitHelper.OnSuccessListener() {
@Override
public void onSuccess(Object o) {
Log.e("", "成功");
}
@Override
public void onFaile() {
Log.e("", "失败");
}
});
}
/**
* 多张图片上传
*/
private void initUpateBitmap2() {
//获取图片路径,这只是个简单的例子,项目开发中会有很多图片需要上传,一般从相册和相机里获取,并且保存到后台服务器时必须自己定义名字
// ,这样就不会发生图片替换(原因名字重复)
File file = new File(Environment.getExternalStorageDirectory() + "/" + "retrofit/" + "ceshi.jpg");
File file2 = new File(Environment.getExternalStorageDirectory() + "/" + "retrofit/" + "ceshi2.jpg");
File file3 = new File(Environment.getExternalStorageDirectory() + "/" + "retrofit/" + "ceshi3.jpg");
File file4 = new File(Environment.getExternalStorageDirectory() + "/" + "retrofit/" + "ceshi4.jpg");
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);
RequestBody requestBody3 = RequestBody.create(MediaType.parse("multipart/form-data"), file3);
RequestBody requestBody4 = RequestBody.create(MediaType.parse("multipart/form-data"), file4);
RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file);
//传一张图片就要增加一个参数
String name = "photo\"; filename=\"ceshi.jpg\"";
String name2 = "photo\"; filename=\"ceshi2.jpg\"";
String name3 = "photo\"; filename=\"ceshi3.jpg\"";
String name4 = "photo\"; filename=\"ceshi4.jpg\"";
HashMap<String, RequestBody> map = new HashMap<>();
map.put(name, requestBody);
map.put(name2, requestBody2);
map.put(name3, requestBody3);
map.put(name4, requestBody4);
RetrofitHelper.getInstance().uploadFile2(map, new RetrofitHelper.OnSuccessListener() {
@Override
public void onSuccess(Object o) {
Log.e("", "成功");
}
@Override
public void onFaile() {
Log.e("", "失败");
}
});
}
接口
//Post文件提交 ,每个键值对都需要用@Part注解键名字
//Multipart 支持文件上传
@Multipart
@POST("拼接参数")
@Multipart
@POST("拼接参数")
Call<TestBean> postFile2(@PartMap HashMap<String,RequestBody> bodyMap, @Field("token") String token);
总结
Retrofit2 的.baseUrl( xxxxxxx / )方法必须以 /(斜线) 结束,
不然会抛出一个IllegalArgumentException,所以如果你看到别的教程没有以 / 结束,
那么多半是直接从Retrofit 1.X 照搬过来的。