Android中OkHttp的使用

作者: Scorpio_青牙 | 来源:发表于2017-06-30 15:13 被阅读112次

    网上有很多OkHttp使用的教程,而我今天要给大家分享的是我自己对OkHttp的使用并且做了简单的封装,希望能给你们带来帮助,话不多说了下面直接上干货了(我使用的是Android Studio)。

    官方的文档

    OkHttp官网地址:http://square.github.io/okhttp/
    OkHttp GitHub地址:https://github.com/square/okhttp

    OKHttp的使用

    Android Studio用户在 Gradle中添加: 
      compile'com.squareup.okhttp3:okhttp:3.8.1'
      compile 'com.squareup.okio:okio:1.13.0'
    Eclipse的用户,添加依赖包即可,Jar包下载地址: okhttp3_Jar okio_Jar

    干货来了(直接上代码)

    1.请求地址配置

    /**
     * 网络访问地址定义
     * @author zcq
     * Created by 2016/4/25.
     */
    public class ApiConfig {
        public final static String API_BSAE = "http://192.168.1.118/help/";
    }
    

    2.接口错误定义

    /**
     * 接口错误定义
     * @author zcq
     * Created by 2017/4/25.
     */
    public enum  ErrorCode {
    
        /**
         * 无错误
         */
        None,
    
        /**
         * 网络错误
         */
        NetworkError,
    
        /**
         * 服务器错误
         */
        ServerError,
    
        /**
         * 数据错误
         */
        DataError
    }
    

    3.数据接口监听器

    /**
     * 数据侦听器接口定义,用于向接口传递单条数据
     * @author zcq
     * Created by 2016/4/25.
     */
    public interface OnDataListener<T> extends OnErrorListener{
        /**
         * 向接口传递单条数据
         * @param isSuccess 接口调用是否成功
         * @param data 待传递的单条数据
         * @param errorCode 接口调用失败时错误码
         * @param errorReason 接口调用失败时的原因
         */
        void onData(boolean isSuccess, T data, int errorCode, String errorReason);
    }
    
    /**
     * 数据侦听器接口定义,用于向接口传递单条数据
     * @author zcq
     * Created by 2016/4/25.
     */
    public interface  OnListListener<T> extends OnErrorListener{
        /**
         * 向接口传递多条数据
         * @param isSuccess 接口调用是否成功
         * @param data 待传递的多条数据
         * @param errorCode 接口调用失败时错误码
         * @param errorReason 接口调用失败时的原因
         */
        void onList(boolean isSuccess, List<T> data, int errorCode, String errorReason);
    }
    
    /**
     * @author zcq
     * Created by 2016/4/25.
     */
    public interface OnImageListener {
        void onImage(int position, String url, Bitmap bitmap);
    }
    
    /**
     * 错误侦听器接口定义,用于向接口传递错误信息
     * @author zcq
     * Created by 2016/4/25.
     */
    public interface OnErrorListener {
    
        /**
         * 向接口传递错误信息
         * @param code 待传递的错误信息
         */
        void onError(ErrorCode code);
    }
    

    4.与服务器通讯接口类定义

    /**
     * 与服务器通讯接口类定义
     * @author zcq
     * Created by 2016/4/25.
     */
    public class HttpHelper {
        private final static boolean DEBUG = true;
        private final static String TAG = "help/HttpHelper";
        protected final static int MESSAGE_DATA = 0;
        protected final static int MESSAGE_ERROR = 1;
    
        /**
         * 接收到网络数据
         * @param event 事件的标识
         * @param response 所接收到的数据
         */
        protected void onData(int event, String response){
        }
    
        /**
         * 接收到网络错误
         * @param event 事件的标识
         * @param code 所接收到的错误码
         */
        protected void onError(int event, ErrorCode code){
        }
    
        static class UIHandler extends Handler {
            private final WeakReference<HttpHelper> ref;
    
            UIHandler(HttpHelper act) {
                this.ref = new WeakReference<>(act);
            }
    
            @Override
            public void handleMessage(Message msg) {
                HttpHelper act = ref.get();
                if (msg.what == MESSAGE_DATA) {
                    act.onData(msg.arg1, msg.obj != null ? msg.obj.toString() : null);
                } else if (msg.what == MESSAGE_ERROR) {
                    act.onError(msg.arg1, (ErrorCode) msg.obj);
                } else {
                    super.handleMessage(msg);
                }
            }
        }
    
        private final UIHandler mHandler = new UIHandler(this);
    
        /**
         * 开始异步访问网络接口
         * @param event 事件编号
         * @param url 接口地址
         * @param params 待提交的参数
         */
        protected synchronized void beginRequest(final int event, final String url, final Map<String, String> params){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    OkHttpClient client = new OkHttpClient();
                    FormBody.Builder formBodayBuilder = new FormBody.Builder();
                    //参数处理
                    if (params != null) {
                        for (String param : params.keySet()) {
                            String value = params.get(param);
                            if (value != null) {
                                formBodayBuilder.add(param, value);
                            }
                        }
                    }
    
                    //设置发出的 request
                    Request post = new Request.Builder()
                            .url(url) //请求的地址
                            .post(formBodayBuilder.build()) //请求的参数
                            .tag(event) //请求标识
                            .build();
                    try {
                        //获取 response
                        Response response = client.newCall(post).execute();
                        if (response.isSuccessful()) {
                            String res = response.body().string();
    //                        Log.i("----API请求返回值----","----***************---res:"+res);
                            if (res != null) {
                                mHandler.obtainMessage(MESSAGE_DATA, event, 0, res).sendToTarget();
                            } else {
                                mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
                            }
                        } else {
                            if (DEBUG) {
                                String res = response.body().toString();
                                if (res != null) {
                                    Log.d(TAG, res);
                                }
                            }
                            mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
                        }
                    } catch (IOException e) {
                        mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.NetworkError).sendToTarget();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        /**
         * 开始异步上传文件
         * @param event 事件编号
         * @param url 接口地址
         * @param params 待提交的参数
         *filesam files 待上传的文件
         */
        protected synchronized void beginUpload(final int event, final String url,
                                                final Map<String, String> params,
                                                final Map<String, String> files) {
            new Thread(new Runnable() {
                @Override
                public synchronized void run() {
                    OkHttpClient client = new OkHttpClient();
                    //以表单方式上传图片文件
                    MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
                    //非文件参数处理
                    if (params != null) {
                        for (String param : params.keySet()) {
                            String value = params.get(param);
                            if (value != null) {
                                builder.addFormDataPart(param, value);
                            }
                        }
                    }
                    //文件参数处理 TODO: MediaType 可提出作为参数
                    MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
                    int i = 0;
                    if(files != null){
                        for (String key : files.keySet()){
                            File file = new File(files.get(key));
                            if(file != null){
                                builder.addFormDataPart("file"+i, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
                            }
                            i++;
                        }
                    }
                    MultipartBody requestBody = builder.build();
    
                    //请求
                    Request post = new Request.Builder()
                            .url(url) //请求的地址
                            .post(requestBody) //请求的参数
                            .tag(event) //请求标识
                            .build();
    
                    try {
                        //获取 response
                        Response response = client.newCall(post).execute();
                        if (response.isSuccessful()) {
                            String res = response.body().string();
                            if (res != null) {
                                mHandler.obtainMessage(MESSAGE_DATA, event, 0, res).sendToTarget();
                            } else {
                                mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
                            }
                        } else {
                            if (DEBUG) {
                                String res = response.body().toString();
                                if (res != null) {
                                    Log.d(TAG, res);
                                }
                            }
                            mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
                        }
                    } catch (IOException e) {
                        mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.NetworkError).sendToTarget();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        /**
         * 开始异步访问网络接口
         * @param event 事件编号
         * @param url 接口地址
         */
        protected synchronized void beginRequest(int event, String url) {
            beginRequest(event, url, null);
        }
    }
    

    5.返回的 JSON 数据进行解析的帮助类

    /**
     * 对 HTTP 返回的 JSON 数据进行解析的帮助类
     * @author zcq
     * Created by 2016/4/25.
     */
    public class JsonHttpHelper extends HttpHelper{
    
        private final static boolean DEBUG = true;
        private final static String TAG = "help/HttpHelper";
    
        /**
         * 接收到网络数据
         *
         * @param event    事件的标识
         * @param response 所接收到的数据
         */
        @Override
        protected void onData(int event, String response) {
            try {
                // 开始解析数据
                JSONObject jsonObject = new JSONObject(response);
                JsonResult jsonResult = new JsonResult();
    
                jsonResult.isSuccess = jsonObject.optBoolean("IsSuccess");
    
                if (jsonResult.isSuccess) {
                    jsonResult.returnValue = jsonObject.optString("ReturnValue");
                } else {
                    jsonResult.errorCode = jsonObject.optInt("ErrorCode");
                    jsonResult.errorReason = jsonObject.optString("ErrorMessage");
                }
                onResult(event, jsonResult);
            } catch (JSONException e) {
                onError(event, ErrorCode.DataError);
            }
        }
    
        /**
         * 接口调用完成时解析后的数据
         *
         * @param event  事件的标识
         * @param result 解析后的数据
         */
        protected void onResult(int event, JsonResult result) {
        }
    
        /**
         * 将解析后的数据交给指定侦听器进行处理
         *
         * @param result   待处理的数据
         * @param cls      返回值对应的类
         * @param <T>      返回值对应的数据类型
         * @param listener 指定的侦听器
         */
        @SuppressWarnings("unchecked")
        protected <T> void handleData(@NonNull JsonResult result, @NonNull Class<T> cls, @Nullable OnErrorListener listener) {
            // 检查侦听器有无注册
            if (listener == null) {
                if (DEBUG) {
                    Log.d(TAG, "the listener not used.");
                }
                return;
            }
    
            // 接口返回失败时不解析返回值
            if (!result.isSuccess) {
                if (listener instanceof OnDataListener) {
                    ((OnDataListener<T>) listener).onData(false, null, result.errorCode, result.errorReason);
                } else if (listener instanceof OnListListener) {
                    ((OnListListener<T>) listener).onList(false, null, result.errorCode, result.errorReason);
                }
                return;
            }
    
            // 将返回值字符串解析成对象
            ObjectMapper objectMapper = new ObjectMapper();
    
            try {
                if (listener instanceof OnDataListener) {
                    // 返回的数据为单个对象
                    T returnValue;
    
                    if (cls.getSimpleName().equals("String")) {
                        returnValue = (T) result.returnValue;
                    } else {
                        returnValue = objectMapper.readValue(result.returnValue, cls);
                    }
                    ((OnDataListener<T>) listener).onData(true, returnValue, 0, null);
    
                } else if (listener instanceof OnListListener) {
                    // 返回的数据为列表数据
                    List<T> returnValue = objectMapper.readValue(
                            result.returnValue, TypeFactory.defaultInstance()
                                    .constructCollectionType(List.class, cls));
    
                    ((OnListListener<T>) listener).onList(true, returnValue, 0, null);
                }
            } catch (IOException e) {
                listener.onError(ErrorCode.DataError);
            }
        }
    }
    

    6.请求返回值JSON格式定义

    /**
     * 网络请求返回值 JSON 格式定义
     * @author zcq
     * Created by 2016/4/25.
     */
    public class JsonResult {
    
        /**
         * 判断接口是否调用成功
         */
        public boolean isSuccess;
    
        /**
         * 接口返回值
         */
        public String returnValue;
    
        /**
         * 接口返回错误时的Code
         */
        public int errorCode;
    
        /**
         * 接口返回的错误信息
         */
        public String errorReason;
    }
    

    以上就是我使用OkHttp自定义的封装请求相关的所有代码了,下面则是使用的测试样例

    • TestApi定义
    /**
     * @author zcq
     * Created by 2016/4/26.
     */
    public class TestApi extends JsonHttpHelper{
    
        //事件定义
        private final  static int EVENT_HOST_API_BASE = 1000;
    
        private final static int EVENT_GET_PERSONAGE_LIST = EVENT_HOST_API_BASE + 1;
    
        //访问地址的定义
        private final static String HOST_SITE = ApiConfig.API_BSAE;
    
        //接口路径
        private final static String URL_GET_PERSONAGE_LIST = HOST_SITE + "mobile/star/getDataLs"; //获取数据列表接口
    
        /**
         * 接口调用完成时解析后的数据
         * @param event 事件的标识
         * @param result 解析后的数据
         */
        @Override
        protected void onResult(int event, JsonResult result) {
            switch (event) {
                case EVENT_GET_PERSONAGE_LIST:
                    handleData(result, Personage.class, mOnGetPersonageLsListener);
                    break;
            }
        }
    
        /**
         * 接收到网络错误
         * @param event 事件的标识
         * @param code 所接收到的错误码
         */
        @Override
        protected void onError(int event, ErrorCode code) {
            switch (event) {
                case EVENT_GET_PERSONAGE_LIST:
                    if(mOnGetPersonageLsListener != null){
                        mOnGetPersonageLsListener.onError(code);
                    }
                    break;
            }
        }
    
        /*********************** 获取List<Entity> **********************/
    
        //获取数据列表接口
        private OnListListener<Personage> mOnGetPersonageLsListener;
    
        /**
         * 获取数据列表接口
         * @param listener 待设置的侦听器
         */
        public void setOnGetPersonageLsListener(OnListListener<Personage> listener){
            this.mOnGetPersonageLsListener = listener;
        }
    
        /**
         * 获取数据列表接口
         * @param pageNum 当前页
         * @param pageSize 分页数
         */
        public void getPersonageLs(int pageNum, int pageSize){
            Map<String, String> params = new HashMap<String, String>();
            params.put("pageNum", String.valueOf(pageNum));
            params.put("pageSize", String.valueOf(pageSize));
            params.put("channel_num","android");
            beginRequest(EVENT_GET_PERSONAGE_LIST, URL_GET_PERSONAGE_LIST, params);
        }
    
        /*********************** 获取Entity String  Boolean**********************/
        //使用 OnDataListener<Entity>   OnDataListener<String>  OnDataListener<Boolean>
        //配置  handleData(result, Entity.class, mOnListener);
        //配置  handleData(result, Boolean.class, mOnListener);
        //配置  handleData(result, String.class, mOnListener);
    }
    
    • 测试Activity
    public class TestAct extends Activity{
    
        private TestApi mApi;
        private TextView text;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.new_ui_test_api);
    
            mApi = new TestApi();
    
            text = (TextView)findViewById(R.id.text);
    
            //Button按钮
            findViewById(R.id.list_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mApi.getPersonageLs(0, 2);
                }
            });
    
    
            //设置侦听器
            mApi.setOnGetPersonageLsListener(new OnListListener<Personage>() {
                @Override
                public void onList(boolean isSuccess, List<Personage> data, int errorCode, String errorReason) {
                    if(isSuccess){
                        text.setText(data.get(0).desc);
                        Toast.makeText(TestAct.this, "List_成功!", Toast.LENGTH_SHORT).show();
                    }else {
                        Toast.makeText(TestAct.this, "List_失败!", Toast.LENGTH_SHORT).show();
                    }
                }
    
                @Override
                public void onError(ErrorCode code) {
                    if(code.equals(ErrorCode.DataError)){
                        Toast.makeText(TestAct.this, "数据错误!", Toast.LENGTH_SHORT).show();
                    }else if(code.equals(ErrorCode.NetworkError)){
                        Toast.makeText(TestAct.this, "网络错误!", Toast.LENGTH_SHORT).show();
                    }else if(code.equals(ErrorCode.ServerError)){
                        Toast.makeText(TestAct.this, "服务器错误!", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }
    
    • 数据实体类 bean
    /**
     * 实体类
     * @author zcq
     * Created by 2016/4/26.
     */
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Personage implements Serializable {
    
        @JsonProperty("column_id")
        public String id;
    
        @JsonProperty("column_name")
        public String name;
    
        @JsonProperty("column_context")
        public String context;
    
        @JsonProperty("column_desc")
        public String desc;
    
        @JsonProperty("column_icon")
        public String imgUrl;
    
        @JsonProperty("create_time")
        public String create_time;
    }
    

    最后附上API接口模板_样例说明

    Paste_Image.png
    • 返回值样例(标准Json格式)
    //返回值为Boolean样例:
    {
        "IsSuccess":true,
        "ReturnValue":true,
        "ErrorMessage":"",
        "ErrorCode":0
    }
    
    //返回值为String样例:
    {
        "IsSuccess":true,
        "ReturnValue":  "http://139.196.192.92/images/info/20160303/20160303110822_head_846141.jpg",
        "ErrorMessage":"",
        "ErrorCode":0
    }
    
    //返回值为List<Entity>样例:
    {
        "IsSuccess":true,
        "ReturnValue":"[{
             "commentId":239,
             "infoId":6375,
             "authorId":40,
             "author":"青牙",
             "head_img_url":"http://139.196.192.92/images/info/20160303/20160303110822_head_846141.jpg",
             "comment_content":"感觉可怜可怜",
             "time":"2017-04-26"
            },
            {
             "commentId":238,
             "infoId":6375,
             "authorId":40,
             "author":"青牙",
             "head_img_url":"http://139.196.192.92/images/info/20160303/20160303110822_head_846141.jpg",
             "comment_content":"过来看看",
             "time":"2017-04-26"}]"
         "ErrorMessage":"",
         "ErrorCode":0
    }
    
    //返回值为Entity样例:
    {
        "IsSuccess":true,
        "ReturnValue":"{
             "infoId":6375,
             "title":"评《锦绣未央》抄袭:放任大\"IP\"抄袭只会劣币驱逐良币",
             "comment_count":4,
             "time":"2017-04-26",
             "is_like":"0",
             "token":"827885c0-db46-4234-a22b-af7aae0f31d9",
             "shareUrl":"http://139.196.192.92/cbtt/admin/info/viewDetailOnPhone?infoId=6375",
        }",
        "ErrorMessage":"",
        "ErrorCode":0
    }
    

    相关文章

      网友评论

      本文标题:Android中OkHttp的使用

      本文链接:https://www.haomeiwen.com/subject/fkwbcxtx.html