说明:
(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; } }
如图: