Retrofit2快速入门使用及文件上传(单上传、多上传)

前言

作者:zkbilian

在开发项目中经常会遇到上传头像的问题,那我们如果使用Retrofit做网络请求时,如何进行使用,在文章的最后有最清晰的使用方法

Retrofit可以认为是Okhttp的 “升级版”,为什么这么说?那是因为其内部默认是基于OkHttp来进行封装的,它们属于同一家公司Square


介绍

这里写图片描述

常用的网络请求方法

@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文件
/**
 *   https://blog.csdn.net/carson_ho/article/details/73732076
 */
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 照搬过来的。

这其实都是简单的使用方式,希望你们能看懂,谷歌推荐搭配Rxjava+Rxandroid+gson 去使用,效率快,逻辑也更加简单

Github:https://github.com/github5210zk/Retrofit

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Retrofit2是一个流行的Android网络框架,可以通过注解和动态代理来简化网络请求的步骤。在使用Retrofit2进行文件上传时,可以使用@Multipart注解和@PartMap注解来实现多文件上传。\[1\] 具体的实现步骤如下: 1. 在Retrofit接口中使用@Multipart注解标记该方法为多部分请求。 2. 使用@POST注解指定上传文件的URL。 3. 使用@PartMap注解将文件参数以Map的形式传递给方法。 4. 在Map中,键是参数的名称,值是RequestBody类型的文件内容。 例如,可以使用以下代码来实现文件上传: ``` @Multipart @POST("upload") Observable<String> uploadFiles(@PartMap Map<String, RequestBody> files); ``` 其中,files是一个Map,键是文件参数的名称,值是RequestBody类型的文件内容。 Retrofit2之所以被广泛使用,是因为它能够根据注解封装网络请求,并通过转化器将原始的HTTP响应内容转化为我们需要的对象。这使得使用Retrofit2非常方便。\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [Retrofit2 multpart多文件上传详解](https://blog.csdn.net/jdsjlzx/article/details/51649382)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [retrofit2上传文件总结](https://blog.csdn.net/u011323666/article/details/52288753)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值