Retrofit 框架的学习
1.Retrofit 简介
1.Retrofit是当下最热门的一个网络请求库,是基于OKhttp和HTTP协议的网络请求框架
https://i-blog.csdnimg.cn/blog_migrate/12ec4ebd360aca614f2b1d6dfdb99aa1.png
2.介绍
Retrofit简介 | |
---|---|
介绍 | 一个RESTful的HTTP网络请求框架 |
作者 | Square |
功能 | 1.基于OKhttp & 遵循Restful的API设计风格; 2.通过注解配置网络请求参数; 3.支持同步/异步网络请求; 4.支持多种类型数据的解析; 5.提供对Rxjava的支持 |
优点 | 功能强大;支持多种数据的解析;支持同步和异步;拓展性好;代码简洁 |
应用场景 | 任何网络请求的需求场景都应该优先选择 |
2.导入依赖
implementation 'com.squareup.retrofit2:retrofit:2.7.0'
3.Retrofit发起Get数据请求
1.创建一个接口api
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
public interface API {
//GET注解里面的参数就是一个URL,就是baseURL后面的那坨坨
@GET("/get/text")
Call<ResponseBody> getJson();
}
所以为什么这儿还要特意把导入的包也要放进来呢?
踩坑!!!Call这个类必须是import retrofit2.Call,别的都是错的,一定要看清楚了
2.创建一个活动,在xml文件内添加一个按钮,用来发送请求
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Retrofit.RetrofitActivity"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Retrofit get请求"
android:textAllCaps="false"
android:onClick="RtgetRequest"
tools:ignore="OnClick" />
</LinearLayout>
3.最后就是.java文件内编译
public class RetrofitActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_retrofit);
}
public void RtgetRequest(View view) {
//首先还是要创建一个Retrofit,并设置baseURL
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://10.0.2.2:9102")
.build();
//创建一个API,retrofit.create()参数传入一个接口
API api = retrofit.create(API.class);
//创建一个任务
Call<ResponseBody> task = api.getJson();
//异步传输,这里和OKhttp一致
task.enqueue(new Callback<ResponseBody>() {
private static final String TAG = "RetrofitActivity";
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.code() == HttpURLConnection.HTTP_OK) {
try {
Log.d(TAG, "onResponse: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
}
4.运行时报错(非代码问题)?怎么解决
如果运行时候报错,在app.gradle文件下面的android{}下面添加如下代码:
compileOptions{
sourceCompatibility 1.8
targetCompatibility 1.8
}
4.retrofit处理请求到的数据并显示到UI上
1.在xml文件上添加一个recycleview,用来显示数据;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Retrofit.RetrofitActivity"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Retrofit get请求"
android:textAllCaps="false"
android:onClick="RtgetRequest"
tools:ignore="OnClick" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/result_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
2.设置一个数据适配器器
public class RtJsonResultAdapter extends RecyclerView.Adapter<RtJsonResultAdapter.InnerHolder> {
private List<GetTextItem.DataDTO> data = new ArrayList<>();
@Override
public InnerHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
//绑定布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.acticity_rtjsonresult_item, parent, false);
return new InnerHolder(view);
}
@Override
public void onBindViewHolder(@NonNull @NotNull InnerHolder holder, int position) {
//绑定数据
TextView tv_name = holder.itemView.findViewById(R.id.nameid);
TextView tv_course = holder.itemView.findViewById(R.id.courseid);
TextView tv_id = holder.itemView.findViewById(R.id.id);
GetTextItem.DataDTO dataDTO = data.get(position);
tv_name.setText(dataDTO.getName());
tv_course.setText(dataDTO.getCourseId());
tv_id.setText(dataDTO.getId());
}
@Override
public int getItemCount() {
return data.size();
}
public void setData(GetTextItem getTextItem) {
data.clear();
data.addAll(getTextItem.getData());
notifyDataSetChanged();
}
public class InnerHolder extends RecyclerView.ViewHolder {
public InnerHolder(@NonNull @NotNull View itemView) {
super(itemView);
}
}
}
3.创建一个展示子项的xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/image_item"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_marginLeft="5dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="作者姓名:"
android:textSize="16sp" />
<TextView
android:id="@+id/name_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="10dp"
android:text="xxx"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView
android:id="@+id/text_courseid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="课程id:"
android:textSize="18sp"
android:layout_alignParentLeft="true"/>
<TextView
android:id="@+id/courseid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/text_courseid"
android:layout_marginLeft="80dp"
android:layout_marginTop="20dp"
android:textSize="16sp"
android:text="123" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView
android:id="@+id/text_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="个人id:"
android:textSize="18sp"
android:layout_alignParentLeft="true"/>
<TextView
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/text_id"
android:layout_marginLeft="80dp"
android:layout_marginTop="20dp"
android:textSize="16sp"
android:text="123" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="#00BCD4"/>
</LinearLayout>
4.在.java文件内编写代码
public class RetrofitActivity extends AppCompatActivity {
private RtJsonResultAdapter rtJsonResultAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_retrofit);
initView();
}
private void initView() {
RecyclerView recyclerView = this.findViewById(R.id.result_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
rtJsonResultAdapter = new RtJsonResultAdapter();
recyclerView.setAdapter(rtJsonResultAdapter);
}
public void RtgetRequest(View view) {
//首先还是要创建一个Retrofit,并设置baseURL
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com")
.build();
//创建一个API
API api = retrofit.create(API.class);
Call<ResponseBody> task = api.getJson();
task.enqueue(new Callback<ResponseBody>() {
private static final String TAG = "RetrofitActivity";
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.code() == HttpURLConnection.HTTP_OK) {
try {
//首先得到获取到的内容
String json = response.body().string();
Log.d(TAG, "onResponse: "+json);
//解析json
Gson gson = new Gson();
GetTextItem getTextItem = gson.fromJson(json,GetTextItem.class);
//在UI中更新数据
updateUI(getTextItem);
Log.d(TAG, "onResponse: "+json);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
private void updateUI(GetTextItem getTextItem) {
rtJsonResultAdapter.setData(getTextItem);
}
}
5.使用转换器把json转换成对象
1.添加依赖
implementation 'com.squareup.retrofit2:converter-gson:2.7.0'
2.在“创建一个请求Request时”添加工厂类
//首先还是要创建一个Retrofit,并设置baseURL
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
3.在API接口里面进行修改
public interface API {
//GET注解里面的参数就是一个URL,就是baseURL后面的那坨坨
@GET("/wxarticle/chapters/json")
Call<GetTextItem> getJson();
}
6.使用@Query 发起带参数的get请求
1.老生常谈的创建一个新的活动,添加一个按钮和一个RecycleView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Retrofit.RetrofitActivity"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Retrofit 使用Query发起get请求"
android:textAllCaps="false"
android:onClick="RtgetRequestQuery"
tools:ignore="OnClick" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/result_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
2.添加一个数据适配器,代码请见第四点
3.用单例模式创建一个RetrofitManager 类,作为Retrofit使用的工具类
这个类并不是使用@Query注解必须需要的东西,而是为了使用Retrofit框架时更加简洁方便而创建的。
public class RetrofitManager {
//首先还是要创建一个Retrofit,并设置baseURL
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
public static Retrofit getReteofit(){
return retrofit;
}
}
4.修改你的api接口
public interface API {
//GET注解里面的参数就是一个URL,就是baseURL后面的那坨坨
@GET("/wxarticle/chapters/json")
Call<GetTextItem> getJson();
//使用QUERY注解来发送带参数的get请求
@GET("/get/param")
Call<GetTextItem> getwithParms(@Query("hanshikai")String keyword,@Query("123456") String password);
}
仔细学习@Query注解的使用方法,注解后边的参数需要写你想传入的参数,然后给这个关键字命名。切记!!注解后面的参数括号内不能有空格
5.在.java文件内编写代码
public void RtgetRequestQuery(View view) {
//创建一个API,之前使用单例模式来创建一个Retrofit;
API api = RetrofitManager.getReteofit().create(API.class);
Call<GetTextItem> task = api.getwithParms("我是一个关键字","123456");
task.enqueue(new Callback<GetTextItem>() {
private static final String TAG = "RetrofitActivity";
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
if (response.code() == HttpURLConnection.HTTP_OK) {
try {
GetTextItem getTextItem = response.body();
updateUI(getTextItem);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
t.printStackTrace();
}
});
}
看,多么简洁的代码。比起HTTP协议的代码简直安逸了不是一星半点哦。记得多用,多用。熟能生巧。
7.Retrofit的@QueryMap注解使用
1.修改api接口
//使用@QueryMap注解(用来解决参数过多的问题)
@GET("/get/param")
Call<GetTextItem> getwithParms(@QueryMap() Map<String,Object> params);
2.在.java文件内编写
//使用QueryMap注解
public void RtgetRequestQueryMap(View view) {
//创建一个API,之前使用单例模式来创建一个Retrofit;
API api = RetrofitManager.getReteofit().create(API.class);
Call<GetTextItem> task = api.getwithParms("我是一个关键字","123456");
task.enqueue(new Callback<GetTextItem>() {
private static final String TAG = "RetrofitActivity";
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
if (response.code() == HttpURLConnection.HTTP_OK) {
try {
GetTextItem getTextItem = response.body();
updateUI(getTextItem);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
t.printStackTrace();
}
});
}
细看来,与@Query注解的使用基本一致,就是多添加一个map集合而已。用法不同但是结果相同,这就是异途同归吗哈哈哈
8.使用POST注解发起带参数的请求
1.创建一个接口
//使用post注解来发起带参数的请求
@POST
Call<GetTextItem> PostwithParams(@Query("这是一个评论") String comment);
2.在.java文件下编辑代码
public void PostWithParams(View view){
API api = RetrofitManager.getReteofit().create(API.class);
Call<GetTextItem> task = api.PostwithParams("返景入深林,复照青苔上");
task.enqueue(new Callback<GetTextItem>() {
private static final String TAG = "PostWithParamsActivity";
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.toString());
}
});
}
9.使用POST注解发起带URL的请求
1.创建接口
//使用post注解来发起带url的请求
@POST
Call<GetTextItem> PostwithUrl(@Url String url);
2.在.java文件内编写代码
//使用post注解来发起带url的请求
public void PostWithUrl(View view){
API api = RetrofitManager.getReteofit().create(API.class);
Call<GetTextItem> task = api.PostwithUrl("返景入深林,复照青苔上");
task.enqueue(new Callback<GetTextItem>() {
private static final String TAG = "PostWithParamsActivity";
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.toString());
}
});
}
10.Retrofit的@Body注解
1.创建新活动,添加新按钮
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用Retrofit的@Body注解"
android:onClick="PostWithBody"
tools:ignore="MissingConstraints,OnClick" />
2.修改api接口
//使用Retrofit的@Body注解
@POST("/post/comment")
Call<GetTextItem> PostwithBody(@Body GetTextItem getTextItem);
注意这里的参数传的是一个实体类
3.在.java文件内编译
//使用Retrofit的@Body注解
public void PostWithBody(View view){
API api = RetrofitManager.getReteofit().create(API.class);
GetTextItem getTextItem = new GetTextItem();
Call<GetTextItem> task = api.PostwithBody(getTextItem);
task.enqueue(new Callback<GetTextItem>() {
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
t.toString();
}
});
}
因为在api中传入的参数是一个实体类,所以在调用接口的方法时,传入的参数也必须是那个实体类
11.Retrofit使用@Part注解上传文件
1.继续创建活动,添加按钮,参考上面代码
2.修改api内容
/@Part注解实现单文件的上传
@Multipart
@POST("/file/upload")
Call<GetTextItem> PostFile(@Part MultipartBody.Part part);
3.编辑代码
//retrofit使用@Part注解来上传文件
@RequiresApi(api = Build.VERSION_CODES.M)
public void RtPostFile(View view){
//内容提供器里面的知识
int permissonResult = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
if(permissonResult != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},REQUEST_CODE);
}
//然后是基操
API api = RetrofitManager.getReteofit().create(API.class);
//创建文件
File file = new File("/storage/emulated/0/Download/1.jpeg");
RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpeg"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("file",file.getName(),requestBody);
Call<GetTextItem> getTextItemCall = api.PostFile(part);
getTextItemCall.enqueue(new Callback<GetTextItem>() {
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.toString());
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
if (requestCode == REQUEST_CODE) {
//TODO:处理权限获取结果
}
}
Retrofit基操之前有一段代码是内容提供器里面的知识。别的都是以前学了的,根据所需要的参数再创建需要的东西。
12.Retrofit使用注解上传多文件
1.添加按钮
2.修改api
//多文件的上传
@Multipart
@POST
Call<GetTextItem> PostFiles(@Part List<MultipartBody.Part> parts);
3. 编辑代码
//使用注解来上传多文件
public void PostFiles(View view){
List<MultipartBody.Part> list = new ArrayList<>();
API api = RetrofitManager.getReteofit().create(API.class);
MultipartBody.Part file1 = createPartByPathAndKry("/storage/emulated/0/Download/1.jpeg", "files");
MultipartBody.Part file2 = createPartByPathAndKry("/storage/emulated/0/Download/2.jpeg", "files");
MultipartBody.Part file3 = createPartByPathAndKry("/storage/emulated/0/Download/3.jpeg", "files");
list.add(file1);
list.add(file2);
list.add(file3);
Call<GetTextItem> task = api.PostFiles(list);
task.enqueue(new Callback<GetTextItem>() {
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.toString());
}
});
}
//封装一下上传文件的代码
public MultipartBody.Part createPartByPathAndKry(String path,String key){
File file = new File(path);
RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpeg"), file);
MultipartBody.Part formData = MultipartBody.Part.createFormData(key, file.getName(), requestBody);
return formData;
}
13.上传文件且带有参数信息
1.添加按钮
2.修改api
//上传文件且携带参数
@Multipart
@POST
Call<GetTextItem> PostFilesWithParam(@Part MultipartBody.Part part,@Part Map<String,String> params);
3.编辑代码
//Retrofit上传文件且携带参数
public void RtPostFilesWithParms(View view){
MultipartBody.Part files = createPartByPathAndKry("/storage/emulated/0/Download/1.jpeg", "files");
Map<String,String> params = new HashMap<>();
params.put("description","这是一条信息");
params.put("isfree","true");
API api = RetrofitManager.getReteofit().create(API.class);
Call<GetTextItem> task = api.PostFilesWithParam(files, params);
task.enqueue(new Callback<GetTextItem>() {
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.toString());
}
});
}
14.使用@Field注解上传表单
1.修改api,然后编辑代码
//提交表单
@FormUrlEncoded
@POST("/login")
Call<GetTextItem> doLogin(@Field("username")String userName,@Field("password")String word);
public void RtPostFileField(View view){
API api = RetrofitManager.getReteofit().create(API.class);
Call<GetTextItem> task = api.doLogin("黄大仙", "123456");
task.enqueue(new Callback<GetTextItem>() {
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.toString());
}
});
}
15.使用@FieldMap注解
1.修改api然后编辑代码
//提交表单
@FormUrlEncoded
@POST("/login")
Call<GetTextItem> doLogin(@FieldMap Map<String,String> map);
//使用Field注解来上传表单
public void RtPostFileField(View view){
API api = RetrofitManager.getReteofit().create(API.class);
Map<String,String> map = new HashMap<>();
map.put("username","大哥");
map.put("password","1234dc");
Call<GetTextItem> task = api.doLogin(map);
task.enqueue(new Callback<GetTextItem>() {
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code== HttpURLConnection.HTTP_OK) {
Log.d(TAG, "onResponse: "+response.body().toString());
}
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: "+t.toString());
}
});
}
16.Retrofit下载文件
1.创建一个新的活动,然后添加一个按钮
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Retrofit.ReteofitDownFile">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="下载文件"
android:onClick="RtDownFile"
tools:ignore="OnClick" />
</LinearLayout>
2.修改api接口,添加一个 下载文件的接口
//下载文件
@GET
Call<GetTextItem> downFile(@Url String url);
3.在.java文件中写代码
public class ReteofitDownFile extends AppCompatActivity {
private static final String TAG = "ReteofitDownFile";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reteofit_down_file);
}
//使用Retrofit下载文件
public void RtDownFile(View view) {
API api = RetrofitManager.getReteofit().create(API.class);
Call<GetTextItem> task = api.downFile("http://www.baidu.com");
task.enqueue(new Callback<GetTextItem>() {
@Override
public void onResponse(Call<GetTextItem> call, Response<GetTextItem> response) {
int code = response.code();
if (code == HttpURLConnection.HTTP_OK) {
//知道文件名称
Headers headers = response.headers();
String fileNameHeader = headers.get("Content-disposition");
String filename = "未命名.png";
if (fileNameHeader != null) {
filename = fileNameHeader.replace("attachment;filename=", "");
Log.d(TAG, "filename: " + filename);
}
for (int i = 0; i < headers.size(); i++) {
String value = headers.value(i);
String name = headers.name(i);
Log.d(TAG, "onResponse: " + value);
}
//写文件,但是这里UI线程,不可以写
writeString2disk(response, filename);
}
}
private void writeString2disk(Response<GetTextItem> response, String filename) {
new Thread(new Runnable() {
@Override
public void run() {
String s = response.body().toString();
InputStream inputStream = response.body().byteStream();
File baseOutFile = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
Log.d(TAG, "run: " + baseOutFile);
File outFile = new File(baseOutFile,filename);
try {
FileOutputStream fos = new FileOutputStream(outFile);
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer))!=-1){
fos.write(buffer,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public void onFailure(Call<GetTextItem> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.toString());
}
});
}
}
基本上都是一样的套路
17.@Header、@Headers、@HeadersMap注解的使用
//@Part注解实现单文件的上传
@Multipart
@POST("/file/upload")
Call<GetTextItem> PostFile(@Part MultipartBody.Part part, @Header("token") String token);
//多文件的上传
@Headers({"token:----","client:android","version:1.0"})
@Multipart
@POST("/files/upload")
Call<GetTextItem> PostFiles(@Part List<MultipartBody.Part> parts);
完结撒花!!!