Retrofit的简单封装

前言

2016年,关于retrofit和okhttp这两个话题非常火,retrofit+okhhtp已经成为Android网络请求的主流框架了,看了一下现在公司的项目,还是使用的原始的HttpURLConnection,瞬间感觉有点low,通过自己的学习,决定对公司的网络请求进行一下改造,在这里做一下简单的总结,希望大家多多指正。

Retrofit

retrofit是一个基于okhttp的,适用于Android,Java的网络请求工具。我觉得它其实就是对okhttp做一下统一的封装,方便广大开发者的更快捷、更方便的使用。如果你对retrofit还不是很熟悉,可以去Retrofit官网了解下,我也会在接下来做个简单的使用说明。它既然这么火,而且已经进行很好的封装了,但是我们为什么还要对它封装呢?因为每个公司的业务不一样,这个框架大而且全,其实很多在我们的业务里面根本使用不到,所以我们需要个性化定制。

  1. 首先创建一个网络请求API的Interface

    public interface GitHubService {
        @GET("users/{user}/repos")
        Call> listRepos(@Path("user") String user);
    }
    
  2. 初始化Retrofit,并创建一个GitHubService interface

    Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();
    
    GitHubService service = retrofit.create(GitHubService.class);
  3. 对GitHubService的方法进行同步或者一部的访问,来实现网络的请求(使用enqueue 或者 execute来执行发起请求,enqueue是是异步执行,而 execute是同步执行)

    Call> repos = service.listRepos("octocat");

上面就是官网对retrofit的简单讲解,下面就进行我们的简单封装。

Interface的改造

因为公司的网络请求都是在common包里面处理的,而和这个包是不会经常改动的,但是每次增加一个求情,都要改动一下common包里面的网络请求的Interface,这个不利于模块的解耦。下面是我对Interface的改造:

public interface NetInterface {
    @GET
    Call get(@Url String url);

    @POST
    Call post(@Url String url, @Body RequestBody body);

    @Multipart
    @POST
    Call updateFile(@Url String url, @Part MultipartBody.Part file, @PartMap HashMap map);
}

Retrofit的简单封装_第1张图片

定义了三个方法,get、post、updateFile对应网络请求的GET、POST和文件上传,这样每次就只需传入一个url就可以进行网络请求,不用每次都去更改。

Retrofit的封装NetUtils

public class NetUtils {
    private static NetUtils INSTANCE;
    private OkHttpClient mClient;
    private Retrofit mRetrofit;
    private ArrayList callLists=new ArrayList<>();

    private NetUtils() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(15, TimeUnit.SECONDS);
        builder.addInterceptor(new NetInterceptor());
        mClient = builder.build();
        mRetrofit = new Retrofit.Builder()
                .baseUrl("")
                .addConverterFactory(FastjsonConverterFactory.create())
                .client(mClient)
                .build();
    }

    public static NetUtils getInstance() {
        if (INSTANCE == null) {
            synchronized (NetUtils.class) {
                if (INSTANCE == null) {
                    INSTANCE = new NetUtils();
                }
            }
        }
        return INSTANCE;
    }


    public Call get(String url) {
        return mRetrofit.create(NetInterface.class).get(url);
    }


    public Call post(String url, FormBody body) {
        return mRetrofit.create(NetInterface.class).post(url, body);
    }

    public Call updateFile(String url, MultipartBody.Part file, HashMap body) {
        return mRetrofit.create(NetInterface.class).updateFile(url, file, body);
    }

}

在这里,可以设置缓存,设置统一的网络拦截器……,我这边写的都比较简单

public class NetInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {

        Response respone = chain.proceed(chain.request());
        Log.d("TAG", respone.request().url() + "");
        Log.d("TAG", respone.body() + "");
        return respone;
    }
}   

简单的打印url,也可以在这里添加一些通用的参数
Retrofit的简单封装_第2张图片

请求工具类NetLoader

public class NetLoader {
    private ArrayList callList = new ArrayList<>();
    private HashMap callMap = new HashMap<>();
    private String TAG = "TAG";

    public Call get(String url, Callback callback) {
        Call call = NetUtils.getInstance().get(url);
        call.enqueue(callback);
        callList.add(call);
        return call;
    }

    public Call get(String url, String tag, Callback callback) {
        Call call = NetUtils.getInstance().get(url);
        callList.add(call);
        return call;
    }

    public Call post(String url, String postStr, Callback callback) {
        FormBody.Builder builder = new FormBody.Builder();
        String[] maps = postStr.split("&");
        for (String s : maps) {
            String key = s.substring(0, s.indexOf("="));
            String value = s.substring(s.indexOf("=") + 1, s.length());
            builder.add(key, value);
        }
        Call call = NetUtils.getInstance().post(url, builder.build());
        call.enqueue(callback);
        callList.add(call);
        return call;

    }
    public Call updateFile(String url, String postStr, String fileKey, File file, Callback callback) {
        HashMap map = new HashMap<>();
        String[] maps = postStr.split("&");
        for (String s : maps) {
            String key = s.substring(0, s.indexOf("="));
            String value = s.substring(s.indexOf("=") + 1, s.length());
            RequestBody body = RequestBody.create(MediaType.parse("text/plain"), value);
            map.put(key, body);

        }
        RequestBody requestFile =
                RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part body =
                MultipartBody.Part.createFormData(fileKey, file.getName(), requestFile);

        Call call = NetUtils.getInstance().updateFile(url, body, map);
        call.enqueue(callback);
        callList.add(call);
        return call;
    }


    public void destroy() {
        for (Call call : callList) {
            call.cancel();
        }
    }

    public void removeCall(Call call) {
        callList.remove(call);
    }

}

其实上面的NetUtils已经满足了我们的网络请求,为什么还要把它包装到NetLoader里面呢?原因是为了我们
我们可以通过在每个Activity或者Fragment里面新建一个netLoader示例,在destroy方法里面调用netloader. destroy()方法,就可以实现与之周期进行绑定,防止异常。

CallBack的封装

我们还可以对请求返回的callback就行同意的处理:

public class NetCallBack implements Callback {
    private WeakReference reference;
    public NetCallBack(Context context){
        reference=new WeakReference(context);
    }

    @Override
    public void onResponse(Call call, Response response) {
        if(response.body()==null){
            Toast.makeText(reference.get(), "返回为空", Toast.LENGTH_SHORT).show();
        }else{
            //TODO 其他的一些判断,如登陆或者其他的统一操作

        }
    }

    @Override
    public void onFailure(Call call, Throwable t) {
        Toast.makeText(reference.get(), "网络连接错误", Toast.LENGTH_SHORT).show();
    }

}

当网络请求失败的时候,我们可以统一的弹窗处理,当用户没登录时,我们可以自己跳到登录页……

以上就是我对网络请求的简单封装,欢迎大家向我吐槽!

你可能感兴趣的:(android,Retrofit)