Android OkHttp3(完美封装)Get异步获取数据、Post异步获取数据、Form表单提交、文件下载

说明:

(1)本项目需要一个:MainActivity.java 类和 activity_main.xml 布局页面。

(2)下载文件需要一个拦截器共2个类:ProgressListener 接口 ProgressResponsBody 封装类。

(3)封装OkHttp3需要4个类:BaseCallBack、BaseOkHttpClient、OkHttpManage、RequestParameter。

1.MainActivity 类:

package com.xxxx.example.activity;

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.tcrj.example.intercept.ProgressListener;
import com.tcrj.example.intercept.ProgressResponsBody;
import com.tcrj.example.okhttp.BaseCallBack;
import com.tcrj.example.okhttp.BaseOkHttpClient;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 首页界面
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btnGetdata;
    private Button btnPostdata;
    private Button btnFormdata;
    private TextView txtState;
    private TextView txtContent;
    private EditText edtAccount;
    private EditText edtPassword;
    private EditText edtFormname;
    private EditText edtFormpwd;
    private Button btnDownload;
    private ProgressBar progress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    /**
     * 获取页面控件
     */
    private void initView() {
        btnGetdata = (Button) findViewById(R.id.btn_getdata);
        btnPostdata = (Button) findViewById(R.id.btn_postdata);
        btnFormdata = (Button) findViewById(R.id.btn_formdata);
        btnDownload = (Button) findViewById(R.id.btn_download);
        txtState = (TextView) findViewById(R.id.txtState);
        txtContent = (TextView) findViewById(R.id.txtContent);
        edtAccount = (EditText) findViewById(R.id.edt_account);
        edtPassword = (EditText) findViewById(R.id.edt_password);
        edtFormname = (EditText) findViewById(R.id.edt_formname);
        edtFormpwd = (EditText) findViewById(R.id.edt_formpwd);
        progress = (ProgressBar) findViewById(R.id.progressBar);
        btnGetdata.setOnClickListener(this);
        btnPostdata.setOnClickListener(this);
        btnFormdata.setOnClickListener(this);
        btnDownload.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_getdata:
                getData();
                break;
            case R.id.btn_postdata:
                String account = edtAccount.getText().toString().trim();
                String password = edtPassword.getText().toString().trim();
                if (TextUtils.isEmpty(account)) {
                    Toast.makeText(this, "请输入账号", Toast.LENGTH_SHORT).show();
                    return;
                }
                if (TextUtils.isEmpty(password)) {
                    Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show();
                    return;
                }
                postSubmit(account, password);
                break;
            case R.id.btn_formdata:
                String name = edtFormname.getText().toString().trim();
                String pwd = edtFormpwd.getText().toString().trim();
                if (TextUtils.isEmpty(name)) {
                    Toast.makeText(this, "请输入账号", Toast.LENGTH_SHORT).show();
                    return;
                }
                if (TextUtils.isEmpty(pwd)) {
                    Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show();
                    return;
                }
                postFormSubmit(name, pwd);
                break;
            case R.id.btn_download:
                downLoadFile();
                break;
        }
    }

    /**
     * Post异步提交:登录
     *
     * @param account
     * @param password
     */
    private void postSubmit(String account, String password) {
        String url = "http://192.168.10.24:8881/Api/GetLoginInfo.ashx?";
        BaseOkHttpClient.newBuilder()
                .addParam("AccountName", account)
                .addParam("LoaPwd", password)
                .post()
                .url(url)
                .build()
                .enqueue(new BaseCallBack() {
                    @Override
                    public void onSuccess(Object o) {
                        txtState.setText("登录成功");
                        Toast.makeText(MainActivity.this, "成功:" + o.toString(), Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(int code) {
                        Toast.makeText(MainActivity.this, "错误编码:" + code, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFailure(Call call, IOException e) {
                        Toast.makeText(MainActivity.this, "失败:" + e.toString(), Toast.LENGTH_SHORT).show();
                    }
                });
    }

    /**
     * GET异步请求数据
     */
    private void getData() {
        String url = "http://www.xxxxx.xxx.cn/jsp/brow/infoList.jsp?";
        BaseOkHttpClient.newBuilder()
                .addParam("cat_id", 14137)
                .addParam("cur_page", 1)
                .addParam("size", 10)
                .get()
                .url(url)
                .build()
                .enqueue(new BaseCallBack() {
                    @Override
                    public void onSuccess(Object o) {
                        Toast.makeText(MainActivity.this, "成功:" + o.toString(), Toast.LENGTH_SHORT).show();
                        txtContent.setText(o.toString());
                    }

                    @Override
                    public void onError(int code) {
                        Toast.makeText(MainActivity.this, "错误编码:" + code, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFailure(Call call, IOException e) {
                        Toast.makeText(MainActivity.this, "失败:" + e.toString(), Toast.LENGTH_SHORT).show();
                    }
                });
    }

    /**
     * Form 表单提交
     */
    private void postFormSubmit(String name, String pwd) {
        String url = "http://192.168.20.101:8080/webProject/servlet/TestServlet";
        BaseOkHttpClient.newBuilder()
                .addParam("username", name)
                .addParam("password", pwd)
                .form()
                .url(url)
                .build()
                .enqueue(new BaseCallBack() {
                    @Override
                    public void onSuccess(Object o) {
                        Toast.makeText(MainActivity.this, "成功:" + o.toString(), Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(int code) {
                        Toast.makeText(MainActivity.this, "错误编码:" + code, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFailure(Call call, IOException e) {
                        Toast.makeText(MainActivity.this, "失败:" + e.toString(), Toast.LENGTH_SHORT).show();
                    }
                });
    }

    String fileName = "book.txt";

    /**
     * 文件下载
     */
    private void downLoadFile() {
        OkHttpClient client = new OkHttpClient.Builder()
                .addNetworkInterceptor(new InterNetInterceptor())
                .build();
        //String urlx = "http://sw.bos.baidu.com/sw-search-sp/software/e73a3ba452ef5/BaiduNetdisk_5.6.0.17.exe";
        //String urlx = "http://gdown.baidu.com/data/wisegame/9db3f36158334e25/baiduwangpan_517.apk";
        String urlx = "https://publicobject.com/helloworld.txt";
        Request request = new Request.Builder()
                .url(urlx)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("MainActivity", e.toString());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                writeFile(response);
            }
        });
    }

    /**
     * Interceptor拦截器方法实现
     */
    public class InterNetInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());
            return response.newBuilder().body(new ProgressResponsBody(response.body(), new ProgBar())).build();
        }
    }

    /**
     * 进度条监听
     */
    private class ProgBar implements ProgressListener {

        @Override
        public void onProgress(final int mProgress, final long contentSize) {
            Log.i("**************下载进度:", String.valueOf(mProgress));
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progress.setProgress(mProgress);
                }
            });
        }

        @Override
        public void onDone(long totalSize) {
            Log.i("下载完成********文件大小为:", String.valueOf(totalSize));
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

    /**
     * 读取文件
     *
     * @param response
     */
    private void writeFile(Response response) {
        InputStream is = null;
        FileOutputStream fos = null;
        is = response.body().byteStream();
        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        File file = new File(path, fileName);
        try {
            fos = new FileOutputStream(file);
            byte[] bytes = new byte[2048];
            int len = 0;
            while ((len = is.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
            is.close();
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (fos != null) {
                    fos.flush();
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.布局文件 activity_main.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="match_parent"
    android:layout_margin="@dimen/activity_horizontal_margin"
    android:orientation="vertical">


    <Button
        android:id="@+id/btn_getdata"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="OkHttp  GET异步获取数据" />

    <EditText
        android:id="@+id/edt_account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入账号"
        android:textColor="@color/colorAccent"
        android:textSize="16sp" />

    <EditText
        android:id="@+id/edt_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入密码"
        android:inputType="textPassword"
        android:textColor="@color/colorAccent"
        android:textSize="16sp" />

    <Button
        android:id="@+id/btn_postdata"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="OkHttp  POST异步获取数据" />

    <EditText
        android:id="@+id/edt_formname"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入账号"
        android:textColor="@color/colorAccent"
        android:textSize="16sp" />

    <EditText
        android:id="@+id/edt_formpwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入密码"
        android:inputType="textPassword"
        android:textColor="@color/colorAccent"
        android:textSize="16sp" />

    <Button
        android:id="@+id/btn_formdata"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="OkHttp  FORM表单提交" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn_download"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="OkHttp  文件下载" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/txtState"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/colorAccent"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/txtContent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/colorPrimary"
                android:textSize="16sp" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

3.拦截器接口:ProgressListener

package com.xxxx.example.intercept;

/**
 * 进度条监听器
 * Created by leict on 2017/6/9.
 */

public interface ProgressListener {
    /**
     * 显示进度
     *
     * @param mProgress
     */
    public void onProgress(int mProgress,long contentSize);

    /**
     * 完成状态
     *
     * @param totalSize
     */
    public void onDone(long totalSize);
}

4.拦截器类

package com.xxxx.example.intercept;

import android.util.Log;

import java.io.IOException;

import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

/**
 * 继承ResponsBody 并重写改方法
 * Created by leict on 2017/6/9.
 */

public class ProgressResponsBody extends ResponseBody {
    private ResponseBody responseBody;
    private BufferedSource bufferedSource;
    private ProgressListener listener;

    public ProgressResponsBody(ResponseBody responseBody, ProgressListener listener) {
        this.responseBody = responseBody;
        this.listener = listener;
    }

    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }

    @Override
    public long contentLength() {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(getSource(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source getSource(Source source) {

        return new ForwardingSource(source) {
            long totalSize = 0;
            long sum = 0;

            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                if (totalSize == 0) {
                    totalSize = contentLength();
                }
                long len = super.read(sink, byteCount);
                sum += (len == -1 ? 0 : len);
                int press = (int) ((sum * 1.0f / totalSize) * 100);
                Log.i("///////////", String.valueOf(totalSize));
                if (len == -1) {
                    listener.onDone(totalSize);
                } else {
                    listener.onProgress(press, totalSize);
                }
                return len;
            }
        };
    }
}

5.回调类封装:BaseCallBack

package com.xxxx.example.okhttp;

import com.google.gson.internal.$Gson$Types;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.Call;

/**
 * 回调函数
 * Created by leict on 2017/6/6.
 */

public abstract class BaseCallBack<T> {
    public Type mType;

    static Type getSuperclassTypeParameter(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            return null;
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
    }

    public BaseCallBack() {
        mType = getSuperclassTypeParameter(this.getClass());
    }

    /**
     * 成功
     *
     * @param t
     */
    public abstract void onSuccess(T t);

    /**
     * 错误代码
     *
     * @param code
     */
    public abstract void onError(int code);

    /**
     * 失败
     *
     * @param call
     * @param e
     */
    public abstract void onFailure(Call call, IOException e);
}

6.监听类:BaseOkHttpClient

package com.xxxx.example.okhttp;

import android.net.Uri;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;

/**
 * 封装OkHttp
 * Created by leict on 2017/6/8.
 */

public class BaseOkHttpClient {
    private Builder mBuilder;

    private BaseOkHttpClient(Builder builder) {
        this.mBuilder = builder;
    }

    public Request buildRequest() {
        Request.Builder builder = new Request.Builder();
        if (mBuilder.method == "GET") {
            builder.url(buildGetRequestParam());
            builder.get();
        } else if (mBuilder.method == "POST") {
            builder.url(mBuilder.url);
            try {
                builder.post(buildPostRequestParam());
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return builder.build();
    }

    /**
     * GET拼接参数
     *
     * @return
     */
    private String buildGetRequestParam() {
        if (mBuilder.params.size() <= 0) {
            return this.mBuilder.url;
        }
        Uri.Builder builder = Uri.parse(mBuilder.url).buildUpon();
        for (RequestParameter p : mBuilder.params) {
            builder.appendQueryParameter(p.getKey(), p.getObj() == null ? "" : p.getObj().toString());
        }
        String url = builder.build().toString();
        return url;
    }

    /**
     * POST拼接参数
     *
     * @return
     */
    private RequestBody buildPostRequestParam() throws JSONException {
        if (mBuilder.isJsonParam) {
            JSONObject jsonObj = new JSONObject();
            for (RequestParameter p : mBuilder.params) {
                jsonObj.put(p.getKey(), p.getObj());
            }
            String json = jsonObj.toString();
            return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        }
        FormBody.Builder builder = new FormBody.Builder();
        for (RequestParameter p : mBuilder.params) {
            builder.add(p.getKey(), p.getObj() == null ? "" : p.getObj().toString());
        }
        return builder.build();
    }

    /**
     * 回调调用
     *
     * @param callBack
     */
    public void enqueue(BaseCallBack callBack) {
        OkHttpManage.getInstance().request(this, callBack);
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public static class Builder {
        private String url;
        private String method;
        private List<RequestParameter> params;
        private boolean isJsonParam;

        public BaseOkHttpClient build() {
            return new BaseOkHttpClient(this);
        }

        private Builder() {
            method = "GET";
            params = new ArrayList<>();
        }

        public Builder url(String url) {
            this.url = url;
            return this;
        }

        /**
         * GET请求
         *
         * @return
         */
        public Builder get() {
            method = "GET";
            return this;
        }

        /**
         * POST请求
         *
         * @return
         */
        public Builder post() {
            method = "POST";
            isJsonParam = true;
            return this;
        }

        /**
         * JSON参数
         *
         * @return
         */
        public Builder json() {
            isJsonParam = true;
            return post();
        }

        /**
         * Form请求
         *
         * @return
         */
        public Builder form() {
            return this;
        }

        /**
         * 添加参数
         *
         * @param key
         * @param value
         * @return
         */
        public Builder addParam(String key, Object value) {
            if (params == null) {
                params = new ArrayList<>();
            }
            params.add(new RequestParameter(key, value));
            return this;
        }
    }
}

7.管理类:OkHttpManage

package com.xxxx.example.okhttp;

import android.os.Handler;
import android.os.Looper;

import com.google.gson.Gson;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Response;

/**
 * OkHttpMange管理类
 * Created by leict on 2017/6/6.
 */

public class OkHttpManage {
    private static OkHttpManage mInstance;
    private OkHttpClient mClient;
    private Handler mHnadler;
    private Gson mGson;

    /**
     * 单例
     *
     * @return
     */
    public static synchronized OkHttpManage getInstance() {
        if (mInstance == null) {
            mInstance = new OkHttpManage();
        }
        return mInstance;
    }

    /**
     * 构造函数
     */
    private OkHttpManage() {
        initOkHttp();
        mHnadler = new Handler(Looper.getMainLooper());
        mGson = new Gson();
    }

    /**
     * 初始化OkHttpClient
     */
    private void initOkHttp() {
        mClient = new OkHttpClient().newBuilder()
                .readTimeout(30000, TimeUnit.SECONDS)
                .connectTimeout(30000, TimeUnit.SECONDS)
                .writeTimeout(30000, TimeUnit.SECONDS)
                .build();
    }

    /**
     * 请求
     *
     * @param client
     * @param callBack
     */
    public void request(BaseOkHttpClient client, final BaseCallBack callBack) {
        if (callBack == null) {
            throw new NullPointerException(" callback is null");
        }
        mClient.newCall(client.buildRequest()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                sendonFailureMessage(callBack, call, e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String result = response.body().string();
                    if (callBack.mType == null || callBack.mType == String.class) {
                        sendonSuccessMessage(callBack, result);
                    } else {
                        sendonSuccessMessage(callBack, mGson.fromJson(result, callBack.mType));
                    }
                    if (response.body() != null) {
                        response.body().close();
                    }
                } else {
                    sendonErrorMessage(callBack, response.code());
                }
            }
        });
    }

    /**
     * 成功信息
     *
     * @param callBack
     * @param result
     */
    private void sendonSuccessMessage(final BaseCallBack callBack, final Object result) {
        mHnadler.post(new Runnable() {
            @Override
            public void run() {
                callBack.onSuccess(result);
            }
        });
    }

    /**
     * 失败信息
     *
     * @param callBack
     * @param call
     * @param e
     */
    private void sendonFailureMessage(final BaseCallBack callBack, final Call call, final IOException e) {
        mHnadler.post(new Runnable() {
            @Override
            public void run() {
                callBack.onFailure(call, e);
            }
        });
    }

    /**
     * 错误信息
     *
     * @param callBack
     * @param code
     */
    private void sendonErrorMessage(final BaseCallBack callBack, final int code) {
        mHnadler.post(new Runnable() {
            @Override
            public void run() {
                callBack.onError(code);
            }
        });
    }
}

8. 参数类:RequestParameter

package com.xxxx.example.okhttp;

/**
 * 参数
 * Created by leict on 2017/6/8.
 */

public class RequestParameter {
    private String key;
    private Object obj;

    public RequestParameter(String key, Object obj) {
        this.key = key;
        this.obj = obj;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }
}

如图:

posted @ 2017-06-12 10:52  逍遥散人95  阅读(13615)  评论(3编辑  收藏  举报