okhttp 封装

okhttp get/post基本用法

okhttp upload/download 上传和下载

对应的项目下载地址:NetFramework

全部单例模式创建方式:单例模式 例子中用到了静态内部类创建单例,对此不了解的可以参考这篇

前两篇文章实践了使用okhttp3.0进行简单的网络交互、获取网络资源等操作,但是可以预料代码会有冗余的情况,我们可以写的更加优雅一点,例子中只是个别的网络请求,实际上我们在做项目的时候会有大量的网络请求,因此我们需要更加简单的使用方式,因此必要的封装是一定的,下面将简单的就okhttp3.0的部分使用做一个简单的封装。网络上已经有了可供使用开源库,本着不重复造轮子的思想,我们其实可以直接使用,但是了解封装的简单思路,了解开源库的封装逻辑还是十分有必要的。

下面是截取前面章节使用的例子,在fragment中有两个按钮,分别进行get和post请求网络数据,获取到的是一串json格式的字符串,我们将这个获取的结果显示在ui空间text上,如此下图:

 

下面是demo代码:

1、封装前使用okhttp经行网络实践

public class NewOkHttpFragment extends Fragment implements View.OnClickListener {

    private static final String TAG = "OkHttpFragment";
    private TextView resultView;
    private Button getView;
    private Button postView;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_okhttp, container, false);
        getView = (Button) view.findViewById(R.id.id_http_get_button);
        postView = (Button) view.findViewById(R.id.id_http_post_button);
        resultView = (TextView) view.findViewById(R.id.id_result_okhttp_view);
        initListener();
        return view;
    }

    private void initListener() {
        getView.setOnClickListener(this);
        postView.setOnClickListener(this);
    }

    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    if (msg.obj == null) {
                        resultView.setText("null");
                    } else {
                        resultView.setText("error:" + msg.obj.toString());
                    }
                    break;
                case 1:
                    if (msg.obj == null) {
                        resultView.setText("null");
                    } else {
                        resultView.setText("response:" + msg.obj.toString());
                    }
                    break;

            }
        }
    };


    /**
     * 测试okhttp的get方法
     */
    private void testOkhttpGet() {
        String url = "http://api.k780.com/?app=weather.history";
        OkHttpClient okHttpClient = new OkHttpClient();
        okhttp3.Request request = new okhttp3.Request.Builder().url(url).get().build();//.get()可以不要,Builder的默认构造方法里面就是get请求
        final Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Message message = Message.obtain();
                message.what = 0;
                message.obj = e.getMessage();
                mHandler.sendMessage(message);
                Log.d(TAG, "onFailure: " + message.obj.toString());
            }

            @Override
            public void onResponse(Call call, okhttp3.Response response) throws IOException {
                Message message = Message.obtain();
                message.what = 1;
                message.obj = response.body().string();//string不能调用两次 被调用一次就关闭了,这里调用两次会报异常
                mHandler.sendMessage(message);
                Log.d(TAG, "response: " + message.obj.toString());
            }
        });

    }


    /**
     * 测试okhttp的post方法
     */
    private void testOkhttpPost() {
        String url = "http://api.k780.com/?app=weather.history";//
        // &weaid=1&date=2018-08-13&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json";

        OkHttpClient okHttpClient = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("weaid", "1")
                .add("date", "2018-08-13")
                .add("appkey", "10003")
                .add("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4")
                .add("format", "json")
                .build();

        okhttp3.Request request = new okhttp3.Request.Builder()
                .url(url)
                .post(body)
                .build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Message message = Message.obtain();
                message.what = 0;
                message.obj = e.getMessage();
                mHandler.sendMessage(message);
                Log.d(TAG, "response: " + message.obj.toString());
            }

            @Override
            public void onResponse(Call call, okhttp3.Response response) throws IOException {
                Message message = Message.obtain();
                message.what = 1;
                message.obj = response.body().string();//string不能调用两次 被调用一次就关闭了,这里调用两次会报异常
                mHandler.sendMessage(message);
                Log.d(TAG, "response: " + message.obj.toString());
            }
        });

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.id_http_get_button:
                testOkhttpGet();
                break;
            case R.id.id_http_post_button:
                testOkhttpPost();
                break;
        }
    }

}

然后我们进行简单的封装,封装前我们需要了解okhttp基本使用没提到的两个知识点

1)设置缓存以及超时

/**
 * 设置超时和缓存
 */
private void settings(Context context) {
    File cacheDir = context.getExternalCacheDir().getAbsoluteFile();//缓存目录
    int cacheSize = 30 * 1024 * 1024;//缓存大小

    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    //注意这里本来是可以采用链式调用的
    builder.connectTimeout(15, TimeUnit.SECONDS);//设置连接超时15s
    builder.readTimeout(15, TimeUnit.SECONDS);//设置读取超时15s
    builder.writeTimeout(15, TimeUnit.SECONDS);//设置写入超时15s
    builder.cache(new Cache(cacheDir, cacheSize));
    builder.build();
}

2)网络请求的cancle

public void cancelWithTag(OkHttpClient client, Object tag) {
    if (client == null || tag == null) return;
    for (Call call : client.dispatcher().queuedCalls()) {
        if (tag.equals(call.request().tag())) {
            call.cancel();
        }
    }

    for (Call call : client.dispatcher().runningCalls()) {
        if (tag.equals(call.request().tag())) {
            call.cancel();
        }
    }
}


public void cancelAll(OkHttpClient client) {
    if (client == null) {
        return;
    }

    for (Call call : client.dispatcher().runningCalls()) {
        call.cancel();
    }

    for (Call call : client.dispatcher().queuedCalls()) {
        call.cancel();
    }

}

2、封装后

/**
 * Created by wwxd on 2018/8/29.
 */
public interface ResponseCallBack {
    public void onFailure(Throwable e);

    public void onSuccess(Response response);

}

public class OKHttpManager {

    public static final String TAG = "OKHttpManager";
    public static final long DEFAULT_TIMEOUT = 60; //默认的超时时间,单位:秒
    private Handler mHandler;
    private OkHttpClient okHttpClient;

    private static volatile OKHttpManager mInstance;//注意这里的使用volatile修饰变量,
    private ResponseCallBack callBack;

    private OKHttpManager() {
        mHandler = new Handler(Looper.getMainLooper());
        okHttpClient = settings();
    }

    /**
     * 使用静态内部类的机制,构造单例
     *
     * @return OKHttpManager
     */
    public static OKHttpManager getInstance() {
        return OKHttpManagerHolder.okHttpManager;
    }

    public static class OKHttpManagerHolder {
        private static OKHttpManager okHttpManager = new OKHttpManager();
    }


    /**
     * 设置超时
     */
    private OkHttpClient settings() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        //注意这里本来是可以采用链式调用的
        builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        builder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        builder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        return builder.build();
    }

    public void doGet(String url, ResponseCallBack callBack) {
        this.callBack = callBack;
        Request request = new Request.Builder().url(url).get().build();
        execute(request);
    }

    public void doPost(String url, RequestBody body, ResponseCallBack callBack) {
        this.callBack = callBack;

        okhttp3.Request request = new okhttp3.Request.Builder()
                .tag(url.hashCode())//通过访问url的hashcode打标签
                .url(url)
                .post(body)
                .build();

        execute(request);

    }

    private void execute(final Request request) {
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {

            @Override
            public void onFailure(Call call, final IOException e) {
                callBack.onFailure(e);
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                //注意这里的string()方法只能被调用一次,否者后面会报错,因为流已经被关闭,所以这里注释掉日志
//                Log.d(TAG,response.body().string());
                callBack.onSuccess(response);
            }
        });

    }

    public Handler getHandler() {
        return mHandler;
    }

    public void runOnUIThread(Runnable runnable) {
        mHandler.post(runnable);
    }

    public void cancelWithTag(OkHttpClient client, Object tag) {
        if (client == null || tag == null) return;
        for (Call call : client.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }

        for (Call call : client.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }


    public void cancelAll(OkHttpClient client) {
        if (client == null) {
            return;
        }

        for (Call call : client.dispatcher().runningCalls()) {
            call.cancel();
        }

        for (Call call : client.dispatcher().queuedCalls()) {
            call.cancel();
        }

    }
}
public class NewOkHttpFragment extends Fragment implements View.OnClickListener {

    private static final String TAG = "NewOkHttpFragment";
    private TextView resultView;
    private Button getView;
    private Button postView;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_okhttp_new, container, false);
        getView = (Button) view.findViewById(R.id.id_http_get_button);
        postView = (Button) view.findViewById(R.id.id_http_post_button);
        resultView = (TextView) view.findViewById(R.id.id_result_okhttp_view);
        initListener();
        return view;
    }

    private void initListener() {
        getView.setOnClickListener(this);
        postView.setOnClickListener(this);
    }


    /**
     * 测试okhttp的get方法
     */
    private void testOkhttpGet() {
        String url = "http://api.k780.com/?app=weather.history";
        OKHttpManager.getInstance().doGet(url, new ResponseCallBack() {
            @Override
            public void onFailure(Throwable e) {
                showResult(e.getMessage());
            }

            @Override
            public void onSuccess(Response response) {
                try {
                    showResult(response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }


    /**
     * 测试okhttp的post方法
     */
    private void testOkhttpPost() {
        String url = "http://api.k780.com/?app=weather.history";
        RequestBody body = new FormBody.Builder()
                .add("weaid", "1")
                .add("date", "2018-08-13")
                .add("appkey", "10003")
                .add("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4")
                .add("format", "json")
                .build();


        OKHttpManager.getInstance().doPost(url, body, new ResponseCallBack() {
            @Override
            public void onFailure(Throwable e) {
                showResult(e.getMessage());
            }

            @Override
            public void onSuccess(Response response) {
                try {
                    showResult(response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }


    private void showResult(final String content) {
        OKHttpManager.getInstance().runOnUIThread(new Runnable() {
            @Override
            public void run() {
                if (resultView != null) {
                    if (TextUtils.isEmpty(content)) {
                        resultView.setText("null");
                    } else {
                        resultView.setText(content);
                    }
                }
            }
        });

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.id_http_get_button:
                testOkhttpGet();
                break;
            case R.id.id_http_post_button:
                testOkhttpPost();
                break;
        }
    }


}

上面仅仅是简单的封装,仅仅只是抛砖引玉,有很多优秀的开源的封装,如:okgo 作者写的特别好,界面如下:

猜你喜欢

转载自blog.csdn.net/weixin_36709064/article/details/82177161
今日推荐