Android okhttp3的使用

1、在模塊中下載或者添加依賴:

implementation 'com.squareup.okhttp3:okhttp:4.7.2'

當你看到這的時候,可能最新的穩定版已經不是3.10.0了,你需要移步官方GitHub來查看最新版本。 官方地址 https://github.com/square/okhttp,另外不要忘了在清單文件聲明訪問Internet的權限,如果使用 DiskLruCache,那還得聲明寫外存的權限。

2、okhttp使用

a、異步GET請求

-new OkHttpClient;
-構造Request對象;
-通過前兩步中的對象構建Call對象;
-通過Call#enqueue(Callback)方法來提交異步請求;

String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
        .url(url)
        .get()//默認就是GET請求,可以不寫
        .build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: ");
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, "onResponse: " + response.body().string());
    }
});

b、同步GET請求

前面幾個步驟和異步方式一樣,只是最後一部是通過 Call#execute() 來提交請求,注意這種方式會阻塞調用線程,所以在Android中應放在子線程中執行,否則有可能引起ANR異常,Android3.0 以後已經不允許在主線程訪問網絡。

String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
        .url(url)
        .build();
final Call call = okHttpClient.newCall(request);
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Response response = call.execute();
            Log.d(TAG, "run: " + response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

c、POST方式提交String

這種方式與前面的區別就是在構造Request對象時,需要多構造一個RequestBody對象,用它來攜帶我們要提交的數據。在構造 RequestBody 需要指定MediaType,用於描述請求/響應 body 的內容類型,關於 MediaType 的更多信息可以查看 RFC 2045,RequstBody的幾種構造方式:

MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
String requestBody = "I am Jdqm.";
Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(mediaType, requestBody))
        .build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: " + e.getMessage());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
        Headers headers = response.headers();
        for (int i = 0; i < headers.size(); i++) {
            Log.d(TAG, headers.name(i) + ":" + headers.value(i));
        }
        Log.d(TAG, "onResponse: " + response.body().string());
    }
});

響應內容

http/1.1 200 OK 
Date:Sat, 10 Mar 2018 05:23:20 GMT 
Content-Type:text/html;charset=utf-8
Content-Length:18
Server:GitHub.com 
Status:200 OK 
X-RateLimit-Limit:60
X-RateLimit-Remaining:52
X-RateLimit-Reset:1520661052
X-CommonMarker-Version:0.17.4
Access-Control-Expose-Headers:ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval

Access-Control-Allow-Origin:*
Content-Security-Policy:default-src 'none'
Strict-Transport-Security:max-age=31536000; includeSubdomains; preload 
X-Content-Type-Options:nosniff 
X-Frame-Options:deny 
X-XSS-Protection:1; mode=block 
X-Runtime-rack:0.019668
Vary:Accept-Encoding 
X-GitHub-Request-Id:1474:20A83:5CC0B6:7A7C1B:5AA36BC8 
onResponse: <p>I am Jdqm.</p>

d、POST方式提交流

RequestBody requestBody = new RequestBody() {
    @Nullable
    @Override
    public MediaType contentType() {
        return MediaType.parse("text/x-markdown; charset=utf-8");
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        sink.writeUtf8("I am Jdqm.");
    }
};

Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(requestBody)
        .build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: " + e.getMessage());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
        Headers headers = response.headers();
        for (int i = 0; i < headers.size(); i++) {
            Log.d(TAG, headers.name(i) + ":" + headers.value(i));
        }
        Log.d(TAG, "onResponse: " + response.body().string());
    }
});

e、POST提交文件

MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("test.md");
Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(mediaType, file))
        .build();
okHttpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: " + e.getMessage());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
        Headers headers = response.headers();
        for (int i = 0; i < headers.size(); i++) {
            Log.d(TAG, headers.name(i) + ":" + headers.value(i));
        }
        Log.d(TAG, "onResponse: " + response.body().string());
    }
});

f、POST方式提交表單

OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
        .add("search", "Jurassic Park")
        .build();
Request request = new Request.Builder()
        .url("https://en.wikipedia.org/w/index.php")
        .post(requestBody)
        .build();

okHttpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: " + e.getMessage());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
        Headers headers = response.headers();
        for (int i = 0; i < headers.size(); i++) {
            Log.d(TAG, headers.name(i) + ":" + headers.value(i));
        }
        Log.d(TAG, "onResponse: " + response.body().string());
    }
});

提交表單時,使用 RequestBody 的實現類FormBody來描述請求體,它可以攜帶一些經過編碼的 key-value 請求體,鍵值對存儲在下面兩個集合中:

  private final List<String> encodedNames;
  private final List<String> encodedValues;

 

3、封裝okhttp

a、定義接口OnFunHttpCallBack

public interface OnFunHttpCallBack {

	void onFailure(int errorCode);

	void onSuccess(String url, String result);

}

b、HttpMethod.java

//okhttp3封裝
public class HttpMethod {

	private final static String TAG = HttpMethod.class.getSimpleName();
	private final static int TIME = 10000;
	public final static int NETWORK_ACCESS_ERROR = 0x0001;
	public final static int SERVER_BACK_ERROR = 0x0002;
	private static HttpMethod m_instance = null;
	private static OkHttpClient m_okHttpClient = null;

	/**
	 * 單一實例
	 */
	public static HttpMethod getInstance() {
		if (m_instance == null) {
			m_instance = new HttpMethod();
			if (m_okHttpClient == null) {
				m_okHttpClient = new OkHttpClient();
				//m_okHttpClient = new OkHttpClient.Builder().connectTimeout(TIME, TimeUnit.SECONDS).readTimeout(TIME, TimeUnit.SECONDS).build();
			}
		}
		return m_instance;
	}

	private class HttpCallback {

		private String m_strUrl = "";
		private OnFunHttpCallBack m_back_http = null; //任務的回調函數

		public HttpCallback(String url, OnFunHttpCallBack back) {
			m_strUrl = url;
			m_back_http = back;
		}

		/**
		 * AsyncHttp的回調函數
		 */
		private Callback m_handler = new Callback() {

			@Override
			public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
				if(response.code() == 200){
					String result = response.body().string();
					if(m_back_http != null){
						m_back_http.onSuccess(m_strUrl, result);
					}
					if (response.body()!=null){
						response.body().close();
					}
					Log.i(TAG, "HTTP-Response-Url: " + m_strUrl + "-----" + result);
				}else{
					if(m_back_http != null){
						m_back_http.onFailure(SERVER_BACK_ERROR);
					}
					Log.e(TAG, "HTTP-Request-Url: " + m_strUrl + " 服務器錯誤(Server error) " + response.code());
				}
			}

			@Override
			public void onFailure(@NotNull Call call, @NotNull IOException e) {
				if(m_back_http != null){
					m_back_http.onFailure(NETWORK_ACCESS_ERROR);
				}
				Log.e(TAG, "HTTP-Request-Url: " + m_strUrl + " 訪問失敗(Access failed)");
			}
		};
	}

	/**
	 * 異步GET請求
	 * 
	 * @param url
	 *            發送請求的URL
	 * @param para
	 *            請求參數,請求參數應該是name1=value1&name2=value2的形式。
	 * @return URL所代表遠程資源的響應
	 */
	public void clientGet(String url, String para, OnFunHttpCallBack back) {
		Log.i(TAG, "HTTP-Request-Url: " + url + "?" + para);
		String reqUrl = url;
		if(para != null && !para.equals("")){
			reqUrl = url + "?" + para;
		}
		//執行get方法
		Request request = new Request.Builder()
				.url(reqUrl)
				.get()//默認就是GET請求,可以不寫
				.build();
		m_okHttpClient.newCall(request).enqueue(new HttpCallback(url, back).m_handler);
	}

	/**
	 * POST方式提交表單
	 *
	 * @param url
	 *            發送請求的URL
	 * @param para
	 *            請求參數,請求參數應該是name1=value1&name2=value2的形式。
	 * @return URL所代表遠程資源的響應
	 */
	public void clientPost(String url, String para, OnFunHttpCallBack back) {
		Log.i(TAG, "HTTP-Request-Url: " + url + "?" + para);
		String[] tmp1 = null;
		String[] tmp2 = null;
		int size = 0;
		//構建表單參數
		FormBody.Builder requestBuild=new FormBody.Builder();
		//解析出各個參數
		if (para != null && !para.equals("")) {
			tmp1 = para.split("&");
			size = tmp1.length;
			for (int i = 0; i < size; i++) {
				tmp2 = tmp1[i].split("=");
				if (tmp2.length != 2) {
					//return;
					continue;
				}
				//設置請求的參數名和參數值
				requestBuild.add(tmp2[0], tmp2[1]);
			}
		}
		//執行post方法
		Request request = new Request.Builder()
				.url(url)
				.post(requestBuild.build())
				.build();
		m_okHttpClient.newCall(request).enqueue(new HttpCallback(url, back).m_handler);
	}

	/**
	 * post文件上傳
	 * 
	 * @param url
	 *            url
	 * @param file
	 *            文件
	 * @param back
	 *            回調接口
	 */
	public void upLoad(String url, File file, OnFunHttpCallBack back) {
		MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
		Request request = new Request.Builder()
				.url(url)
				.post(RequestBody.create(file, mediaType))
				.build();
		m_okHttpClient.newCall(request).enqueue(new HttpCallback(url, back).m_handler);
	}
}

c、HttpTask.java

public class HttpTask {

	private String m_strUrl = "";
	private String m_strPara = "";
	private File m_file = null;
	private OnFunHttpCallBack m_back_http = null;// 任務的回調函數

	public HttpTask(String url, String para, OnFunHttpCallBack back) {
        m_strUrl = url;
        m_strPara = para;
        m_back_http = back;
    }

    public HttpTask(String url, File file, OnFunHttpCallBack back) {
        m_strUrl = url;
        m_file = file;
        m_back_http = back;
    }

	public void runPost() {
		HttpMethod.getInstance().clientPost(m_strUrl, m_strPara, m_back_http);
	}

	public void runGet() {
		HttpMethod.getInstance().clientGet(m_strUrl, m_strPara, m_back_http);
	}

	public void upLoad() {
		HttpMethod.getInstance().upLoad(m_strUrl, m_file, m_back_http);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章