目錄
一、okhttp介紹
1. OkHttpClient類(lèi):
?常用方法:
2. Request類(lèi):
?常用方法:
3. Response類(lèi):
常用方法:
4. Call類(lèi):
常用方法:?
5. Interceptor接口:
常用方法:?
6. FormBody類(lèi):
常用方法:
7. MultipartBody類(lèi):
?常用方法:
8. WebSocket類(lèi):
常用方法:
二、okhttp使用方法
1、添加依賴(lài):
2、創(chuàng)建OkHttpClient對(duì)象:
3、創(chuàng)建Request對(duì)象:
4、發(fā)送同步請(qǐng)求:?
5、發(fā)送異步請(qǐng)求?
三、okhttp例子
省的json數(shù)據(jù)格式:?
?市的json數(shù)據(jù)格式:?
?縣的json數(shù)據(jù)格式:
?MainActivity:
?Utility :
?HttpTool :
Province :?
?City:
County :?
activity_main:?
litepal.xml:?
AndroidManifest:?
依賴(lài):?
運(yùn)行結(jié)果:
一、okhttp介紹
????????OkHttp是一個(gè)開(kāi)源的HTTP客戶(hù)端庫(kù),常用于Android應(yīng)用程序中進(jìn)行網(wǎng)絡(luò)請(qǐng)求。以下是OkHttp的一些常用類(lèi)和方法:
1. OkHttpClient類(lèi):
????????OkHttpClient是OkHttp庫(kù)的核心類(lèi),用于創(chuàng)建和配置HTTP請(qǐng)求的客戶(hù)端。它提供了各種設(shè)置和配置選項(xiàng),如連接超時(shí)、讀寫(xiě)超時(shí)、攔截器等。
?常用方法:
-
newBuilder()
:創(chuàng)建一個(gè)新的OkHttpClient.Builder實(shí)例,用于配置和構(gòu)建OkHttpClient對(duì)象。 -
addInterceptor(Interceptor interceptor)
:添加一個(gè)Interceptor攔截器,用于在發(fā)送請(qǐng)求和接收響應(yīng)時(shí)對(duì)其進(jìn)行處理。例如,可以使用攔截器對(duì)請(qǐng)求進(jìn)行身份驗(yàn)證、日志記錄或數(shù)據(jù)轉(zhuǎn)換等操作。 -
connectTimeout(long timeout, TimeUnit unit)
:設(shè)置連接超時(shí)時(shí)間??梢灾付ㄒ粋€(gè)時(shí)間值和時(shí)間單位來(lái)限制與服務(wù)器建立連接的最長(zhǎng)時(shí)間。 -
readTimeout(long timeout, TimeUnit unit)
:設(shè)置讀取超時(shí)時(shí)間??梢灾付ㄒ粋€(gè)時(shí)間值和時(shí)間單位來(lái)限制從服務(wù)器讀取數(shù)據(jù)的最長(zhǎng)時(shí)間。 -
writeTimeout(long timeout, TimeUnit unit)
:設(shè)置寫(xiě)入超時(shí)時(shí)間。可以指定一個(gè)時(shí)間值和時(shí)間單位來(lái)限制向服務(wù)器寫(xiě)入數(shù)據(jù)的最長(zhǎng)時(shí)間。 -
retryOnConnectionFailure(boolean retry)
:設(shè)置是否重試連接失敗的請(qǐng)求。默認(rèn)情況下,OkHttpClient會(huì)自動(dòng)重試請(qǐng)求,但可以通過(guò)該方法禁用重試。 -
followRedirects(boolean followRedirects)
:設(shè)置是否自動(dòng)遵循重定向。默認(rèn)情況下,OkHttpClient會(huì)自動(dòng)遵循重定向,但可以通過(guò)該方法禁用自動(dòng)重定向。 -
cache(Cache cache)
:設(shè)置緩存。可以傳入一個(gè)Cache對(duì)象,用于緩存網(wǎng)絡(luò)請(qǐng)求的響應(yīng)數(shù)據(jù)。 -
dispatcher(Dispatcher dispatcher)
:設(shè)置Dispatcher調(diào)度器??梢詡魅胍粋€(gè)自定義的Dispatcher對(duì)象,用于控制并發(fā)請(qǐng)求數(shù)量和線程池的行為。 -
proxy(Proxy proxy)
:設(shè)置代理服務(wù)器??梢灾付ㄒ粋€(gè)Proxy對(duì)象,用于將請(qǐng)求通過(guò)代理發(fā)送到目標(biāo)服務(wù)器。
2. Request類(lèi):
????????Request類(lèi)用于構(gòu)建HTTP請(qǐng)求??梢酝ㄟ^(guò)Request.Builder來(lái)創(chuàng)建一個(gè)Request對(duì)象,并設(shè)置URL、請(qǐng)求方法(GET、POST等)、請(qǐng)求頭、請(qǐng)求體等。
?常用方法:
-
newBuilder()
:創(chuàng)建一個(gè)新的Request.Builder實(shí)例,用于構(gòu)建和配置Request對(duì)象。 -
url(String url)
:設(shè)置請(qǐng)求的URL地址??梢詡魅胍粋€(gè)字符串類(lèi)型的URL地址作為參數(shù)。 -
method(String method, RequestBody body)
:設(shè)置請(qǐng)求的HTTP方法和請(qǐng)求體。可以指定請(qǐng)求的HTTP方法(如GET、POST、PUT等)和請(qǐng)求體RequestBody對(duì)象。 -
header(String name, String value)
:添加請(qǐng)求頭。可以通過(guò)該方法添加自定義的請(qǐng)求頭參數(shù),需要提供參數(shù)名和參數(shù)值。 -
headers(Headers headers)
:設(shè)置請(qǐng)求頭集合??梢酝ㄟ^(guò)該方法一次性設(shè)置多個(gè)請(qǐng)求頭,需要傳入Headers對(duì)象。 -
cacheControl(CacheControl cacheControl)
:設(shè)置緩存控制策略。可以傳入一個(gè)CacheControl對(duì)象,用于控制請(qǐng)求的緩存行為。 -
tag(Object tag)
:設(shè)置請(qǐng)求的標(biāo)簽。可以傳入一個(gè)Object類(lèi)型的標(biāo)簽,用于在后續(xù)操作中標(biāo)識(shí)和識(shí)別該請(qǐng)求。 -
build()
:構(gòu)建Request對(duì)象。在配置完成后,使用該方法來(lái)構(gòu)建最終的Request對(duì)象。
3. Response類(lèi):
????????Response類(lèi)表示HTTP響應(yīng)。當(dāng)發(fā)送HTTP請(qǐng)求后,可以通過(guò)Response對(duì)象獲取服務(wù)器返回的響應(yīng)信息,包括狀態(tài)碼、響應(yīng)頭、響應(yīng)體等。
常用方法:
-
code()
:獲取HTTP響應(yīng)的狀態(tài)碼。返回一個(gè)整型值,表示HTTP響應(yīng)的狀態(tài)碼。 -
message()
:獲取HTTP響應(yīng)的狀態(tài)消息。返回一個(gè)字符串,表示HTTP響應(yīng)的狀態(tài)消息。 -
body()
:獲取HTTP響應(yīng)的響應(yīng)體。返回一個(gè)ResponseBody對(duì)象,用于獲取和處理響應(yīng)的具體數(shù)據(jù)。 -
headers()
:獲取HTTP響應(yīng)的響應(yīng)頭。返回一個(gè)Headers對(duì)象,用于獲取和處理響應(yīng)的頭部信息。 -
isSuccessful()
:判斷HTTP響應(yīng)是否成功。返回一個(gè)布爾值,表示HTTP響應(yīng)是否成功(狀態(tài)碼在200-299之間)。 -
cacheResponse()
:獲取緩存的HTTP響應(yīng)。如果請(qǐng)求使用了緩存,并且有對(duì)應(yīng)的緩存響應(yīng),則返回一個(gè)Response對(duì)象,否則返回null。 -
networkResponse()
:獲取網(wǎng)絡(luò)的HTTP響應(yīng)。如果請(qǐng)求是通過(guò)網(wǎng)絡(luò)發(fā)送的,并且有對(duì)應(yīng)的網(wǎng)絡(luò)響應(yīng),則返回一個(gè)Response對(duì)象,否則返回null。 -
priorResponse()
:獲取前一個(gè)HTTP響應(yīng)。如果請(qǐng)求有關(guān)聯(lián)的前一個(gè)HTTP響應(yīng),則返回一個(gè)Response對(duì)象,否則返回null。 -
request()
:獲取與該HTTP響應(yīng)相關(guān)聯(lián)的請(qǐng)求。返回一個(gè)Request對(duì)象,表示與該響應(yīng)相關(guān)聯(lián)的請(qǐng)求。
4. Call類(lèi):
????????Call類(lèi)表示一個(gè)異步的HTTP請(qǐng)求任務(wù)。通過(guò)OkHttpClient的newCall方法創(chuàng)建一個(gè)Call對(duì)象,然后可以使用enqueue方法發(fā)送異步請(qǐng)求,并通過(guò)回調(diào)函數(shù)處理響應(yīng)結(jié)果。
常用方法:?
-
execute()
:同步執(zhí)行HTTP請(qǐng)求并返回Response對(duì)象。該方法會(huì)阻塞當(dāng)前線程,直到獲取到完整的響應(yīng)結(jié)果。 -
enqueue(Callback callback)
:異步執(zhí)行HTTP請(qǐng)求并通過(guò)回調(diào)函數(shù)接收結(jié)果。該方法將請(qǐng)求放入請(qǐng)求隊(duì)列中,并在后臺(tái)線程執(zhí)行,執(zhí)行完成后通過(guò)Callback接口回調(diào)返回結(jié)果。 -
cancel()
:取消HTTP請(qǐng)求。如果HTTP請(qǐng)求尚未執(zhí)行完畢,可以調(diào)用該方法取消正在進(jìn)行的請(qǐng)求。 -
isExecuted()
:判斷HTTP請(qǐng)求是否已經(jīng)執(zhí)行。返回一個(gè)布爾值,表示HTTP請(qǐng)求是否已經(jīng)執(zhí)行。 -
isCanceled()
:判斷HTTP請(qǐng)求是否已經(jīng)取消。返回一個(gè)布爾值,表示HTTP請(qǐng)求是否已經(jīng)取消。 -
timeout()
:獲取超時(shí)設(shè)置。返回一個(gè)Timeout對(duì)象,用于獲取和設(shè)置連接、讀取和寫(xiě)入的超時(shí)時(shí)間。 -
request()
:獲取與該Call相關(guān)聯(lián)的請(qǐng)求。返回一個(gè)Request對(duì)象,表示與該Call相關(guān)聯(lián)的HTTP請(qǐng)求。 -
clone()
:創(chuàng)建Call對(duì)象的副本。返回一個(gè)新的Call對(duì)象,與原始的Call對(duì)象共享相同的配置和請(qǐng)求信息。
5. Interceptor接口:
????????Interceptor接口可以用于對(duì)HTTP請(qǐng)求和響應(yīng)進(jìn)行攔截和處理??梢詫?shí)現(xiàn)自定義的Interceptor來(lái)對(duì)請(qǐng)求進(jìn)行修改、添加請(qǐng)求頭、記錄日志等操作。
常用方法:?
-
Response intercept(Chain chain)
:攔截并處理請(qǐng)求和響應(yīng)。該方法接收一個(gè)Chain對(duì)象作為參數(shù),可以通過(guò)該對(duì)象獲取請(qǐng)求信息并執(zhí)行下一個(gè)攔截器或者發(fā)起實(shí)際的網(wǎng)絡(luò)請(qǐng)求。 -
interface Chain
:表示攔截器鏈中的一環(huán),用于傳遞請(qǐng)求和響應(yīng)以及控制攔截器的執(zhí)行流程。Chain接口擁有以下方法:
-
Connection connection()
:獲取當(dāng)前攔截器鏈的連接對(duì)象。 -
Request request()
:獲取當(dāng)前攔截器鏈的請(qǐng)求對(duì)象。 -
Response proceed(Request request)
:執(zhí)行下一個(gè)攔截器,并返回最終的響應(yīng)結(jié)果。
6. FormBody類(lèi):
? ? ? ? FormBody類(lèi)是OkHttp庫(kù)中用于構(gòu)建表單形式的請(qǐng)求體的類(lèi)。它提供了一些方法來(lái)添加表單字段和值,并生成最終的請(qǐng)求體數(shù)據(jù)。
常用方法:
-
add(String name, String value)
:添加表單字段和值??梢远啻握{(diào)用該方法,以添加多個(gè)表單字段和對(duì)應(yīng)的值。 -
encodedName(int index)
:獲取編碼后的表單字段名。傳入索引值,返回對(duì)應(yīng)位置的編碼后的表單字段名。 -
encodedValue(int index)
:獲取編碼后的表單字段值。傳入索引值,返回對(duì)應(yīng)位置的編碼后的表單字段值。 -
name(int index)
:獲取未編碼的表單字段名。傳入索引值,返回對(duì)應(yīng)位置的未編碼的表單字段名。 -
value(int index)
:獲取未編碼的表單字段值。傳入索引值,返回對(duì)應(yīng)位置的未編碼的表單字段值。 -
size()
:獲取表單字段的數(shù)量。返回一個(gè)整型值,表示表單字段的數(shù)量。 -
contentType()
:獲取請(qǐng)求體的媒體類(lèi)型。返回一個(gè)MediaType對(duì)象,表示請(qǐng)求體的媒體類(lèi)型,默認(rèn)為"application/x-www-form-urlencoded"。 -
contentLength()
:獲取請(qǐng)求體的長(zhǎng)度。返回一個(gè)長(zhǎng)整型值,表示請(qǐng)求體的字節(jié)長(zhǎng)度。 -
toString()
:將FormBody轉(zhuǎn)換為字符串。返回一個(gè)字符串,表示FormBody的內(nèi)容。
7. MultipartBody類(lèi):
???????MultipartBody類(lèi)是OkHttp庫(kù)中用于構(gòu)建多部分(multipart)請(qǐng)求體的類(lèi)。它允許在單個(gè)請(qǐng)求中包含多個(gè)不同類(lèi)型的數(shù)據(jù),如文本、文件等。
?常用方法:
-
create(MediaType type, RequestBody... parts)
:創(chuàng)建一個(gè)MultipartBody對(duì)象。需要傳入媒體類(lèi)型和多個(gè)RequestBody實(shí)例。 -
type()
:獲取請(qǐng)求體的媒體類(lèi)型。返回一個(gè)MediaType對(duì)象,表示請(qǐng)求體的媒體類(lèi)型,默認(rèn)為"multipart/form-data"。 -
boundary()
:獲取邊界字符串。返回一個(gè)字符串,表示請(qǐng)求體的邊界字符串。 -
contentType()
:獲取請(qǐng)求體的完整媒體類(lèi)型。返回一個(gè)字符串,表示請(qǐng)求體的完整媒體類(lèi)型,包括媒體類(lèi)型和邊界字符串。 -
parts()
:獲取請(qǐng)求體的各個(gè)部分。返回一個(gè)List<RequestBody>,表示請(qǐng)求體中的所有部分。 -
writeTo(BufferedSink sink)
:將MultipartBody寫(xiě)入到緩沖區(qū)。需要傳入一個(gè)BufferedSink對(duì)象,用于寫(xiě)入請(qǐng)求體的數(shù)據(jù)。 -
contentLength()
:獲取請(qǐng)求體的長(zhǎng)度。返回一個(gè)長(zhǎng)整型值,表示請(qǐng)求體的字節(jié)長(zhǎng)度。 -
addPart(Headers headers, RequestBody body)
:添加一個(gè)部分到請(qǐng)求體中。可以傳入自定義的請(qǐng)求頭Headers對(duì)象和對(duì)應(yīng)的RequestBody實(shí)例。 -
addFormDataPart(String name, @Nullable String filename, RequestBody body)
:添加一個(gè)表單數(shù)據(jù)部分到請(qǐng)求體中。需要傳入字段名name、可選的文件名filename和RequestBody實(shí)例。 -
addFormDataPart(String name, @Nullable String filename, MediaType contentType, ByteString content)
:添加一個(gè)表單數(shù)據(jù)部分到請(qǐng)求體中。需要傳入字段名name、可選的文件名filename、媒體類(lèi)型contentType和內(nèi)容content。
8. WebSocket類(lèi):
????????WebSocket類(lèi)用于進(jìn)行WebSocket通信。可以建立與服務(wù)器的WebSocket連接,并進(jìn)行雙向通信。
常用方法:
-
request()
:獲取與該WebSocket相關(guān)聯(lián)的請(qǐng)求。返回一個(gè)Request對(duì)象,表示與該WebSocket相關(guān)聯(lián)的HTTP請(qǐng)求。 -
queueSize()
:獲取待發(fā)送的消息隊(duì)列大小。返回一個(gè)整型值,表示待發(fā)送的消息隊(duì)列中的消息數(shù)量。 -
send(String text)
:發(fā)送文本消息??梢詡魅胍粋€(gè)字符串類(lèi)型的消息內(nèi)容,將其作為文本消息發(fā)送給服務(wù)器。 -
send(ByteString bytes)
:發(fā)送二進(jìn)制消息。可以傳入一個(gè)ByteString對(duì)象,將其作為二進(jìn)制消息發(fā)送給服務(wù)器。 -
close(int code, String reason)
:關(guān)閉WebSocket連接??梢詡魅胍粋€(gè)整型的關(guān)閉碼(如1000表示正常關(guān)閉)、一個(gè)字符串的關(guān)閉原因,以便向服務(wù)器發(fā)送關(guān)閉幀,并關(guān)閉WebSocket連接。 -
cancel()
:取消WebSocket連接。如果WebSocket連接尚未關(guān)閉,可以調(diào)用該方法取消連接。 -
send(Request request, WebSocketListener listener)
:發(fā)送指定請(qǐng)求的WebSocket消息??梢詡魅胍粋€(gè)Request對(duì)象和一個(gè)WebSocketListener對(duì)象,將該請(qǐng)求發(fā)送給服務(wù)器,并通過(guò)WebSocketListener監(jiān)聽(tīng)回調(diào)處理結(jié)果。 -
addListener(WebSocketListener listener)
:添加WebSocket事件監(jiān)聽(tīng)器??梢詡魅胍粋€(gè)WebSocketListener對(duì)象,用于監(jiān)聽(tīng)WebSocket連接狀態(tài)、收到消息等事件。 -
removeListener(WebSocketListener listener)
:移除WebSocket事件監(jiān)聽(tīng)器??梢詡魅胍粋€(gè)WebSocketListener對(duì)象,將其從WebSocket的監(jiān)聽(tīng)器列表中移除。
二、okhttp使用方法
1、添加依賴(lài):
????????在項(xiàng)目的build.gradle文件中添加OkHttp的依賴(lài)項(xiàng)。
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
2、創(chuàng)建OkHttpClient對(duì)象:
????????通過(guò)new OkHttpClient()
創(chuàng)建一個(gè)OkHttpClient實(shí)例,用于發(fā)送HTTP請(qǐng)求。
OkHttpClient client = new OkHttpClient();
3、創(chuàng)建Request對(duì)象:
????????使用Request.Builder
構(gòu)建一個(gè)請(qǐng)求對(duì)象,并指定URL地址、請(qǐng)求頭、請(qǐng)求體等相關(guān)信息。
Request request = new Request.Builder()
.url("https://example.com/api")
.header("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonBody))
.build();
4、發(fā)送同步請(qǐng)求:?
????????使用client.newCall(request).execute()
發(fā)送同步請(qǐng)求,并獲得Response對(duì)象。?
try (Response response = client.newCall(request).execute()) {
// 處理響應(yīng)結(jié)果
if (response.isSuccessful()) {
String responseBody = response.body().string();
// ...
} else {
// 請(qǐng)求失敗處理
}
} catch (IOException e) {
// IO異常處理
}
5、發(fā)送異步請(qǐng)求?
?????????使用client.newCall(request).enqueue(Callback)
發(fā)送異步請(qǐng)求,并通過(guò)Callback回調(diào)處理響應(yīng)結(jié)果。
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 請(qǐng)求失敗處理
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 處理響應(yīng)結(jié)果
if (response.isSuccessful()) {
String responseBody = response.body().string();
// ...
} else {
// 請(qǐng)求失敗處理
}
}
});
????????在以上示例中,我們首先創(chuàng)建了一個(gè)OkHttpClient對(duì)象,并使用Request.Builder構(gòu)建了一個(gè)請(qǐng)求對(duì)象。然后,可以選擇性地發(fā)送同步或異步請(qǐng)求。對(duì)于同步請(qǐng)求,直接調(diào)用execute()
方法并處理響應(yīng)結(jié)果;對(duì)于異步請(qǐng)求,使用enqueue(Callback)
方法并通過(guò)Callback回調(diào)處理響應(yīng)結(jié)果。
????????當(dāng)處理完請(qǐng)求后,需要注意關(guān)閉Response對(duì)象的資源,以避免內(nèi)存泄漏。
三、okhttp例子
? ? ? ? 下面例子是郭霖大神的第一行代碼中的酷歐天氣網(wǎng)絡(luò)請(qǐng)求地名的代碼。?
省的json數(shù)據(jù)格式:?
http://guolin.tech/api/china
?
?市的json數(shù)據(jù)格式:?
?http://guolin.tech/api/china/16
?縣的json數(shù)據(jù)格式:
?MainActivity:
package com.example.okhttpdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.okhttpdemo.Bean.City;
import com.example.okhttpdemo.Bean.County;
import com.example.okhttpdemo.Bean.Province;
import org.litepal.LitePal;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import okhttp3.internal.Util;
public class MainActivity extends AppCompatActivity {
public static final int CURRENT_PAGE_PROVINCE = 0;
public static final int CURRENT_PAGE_CITY = 1;
public static final int CURRENT_PAGE_COUNTY = 2;
private List<Province> mProvinces;
private List<City> mCities;
private List<County> mCounties;
private TextView titleTV;
private Button backBtn;
private ListView mListView;
private List<String> mListData = new ArrayList<>();
private ArrayAdapter<String> mAdapter;
private ProgressDialog progressDialog;
private int currentPage;
private Province mCurrentProvince;
private City mCurrentCity;
private County mCurrentCounty;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LitePal.initialize(this);
initView();
}
private void initView() {
mListView = findViewById(R.id.list_view);
backBtn = findViewById(R.id.back_button);
titleTV= findViewById(R.id.title_text);
backBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (currentPage==CURRENT_PAGE_COUNTY){
queryCities();
}else if(currentPage == CURRENT_PAGE_CITY){
queryProvinces();
}
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch (currentPage){
case CURRENT_PAGE_PROVINCE:
mCurrentProvince = mProvinces.get(position);
queryCities();
break;
case CURRENT_PAGE_CITY:
mCurrentCity = mCities.get(position);
queryCounty();
break;
case CURRENT_PAGE_COUNTY:
mCurrentCounty = mCounties.get(position);
Toast.makeText(MainActivity.this,"點(diǎn)擊了"+mCurrentProvince.getProvinceName()+mCurrentCity.getCityName()+mCurrentCounty.getCountyName(),Toast.LENGTH_LONG).show();
break;
}
}
});
mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mListData);
queryProvinces();
mListView.setAdapter(mAdapter);
}
private void queryProvinces(){
titleTV.setText("中國(guó)");
backBtn.setVisibility(View.GONE);
// 從數(shù)據(jù)庫(kù)中找
mProvinces = LitePal.findAll(Province.class);
if (mProvinces.size()>0){
mListData.clear();
for (Province province:mProvinces){
mListData.add(province.getProvinceName());
}
mAdapter.notifyDataSetChanged();
currentPage = CURRENT_PAGE_PROVINCE;
}else {
String url = "http://guolin.tech/api/china";
queryFromServer(url,CURRENT_PAGE_PROVINCE);
}
}
private void queryFromServer(String url, int type) {
showProgressDialog();
HttpTool.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
closeProgressDialog();
Toast.makeText(MainActivity.this,"加載失?。。?!",Toast.LENGTH_LONG).show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
boolean result = false;
switch (type){
case CURRENT_PAGE_PROVINCE:
result = Utility.handleProvinceResponse(response.body().string());
break;
case CURRENT_PAGE_CITY:
result = Utility.handleCitiesResponse(response.body().string(),mCurrentProvince.getId());
break;
case CURRENT_PAGE_COUNTY:
result = Utility.handleCountyResponse(response.body().string(),mCurrentCity.getId());
break;
}
if (result){
runOnUiThread(new Runnable() {
@Override
public void run() {
closeProgressDialog();
switch (type){
case CURRENT_PAGE_PROVINCE:
queryProvinces();
break;
case CURRENT_PAGE_CITY:
queryCities();
break;
case CURRENT_PAGE_COUNTY:
queryCounty();
break;
}
}
});
}
}
});
}
private void queryCounty() {
titleTV.setText(mCurrentCity.getCityName());
backBtn.setVisibility(View.VISIBLE);
// 從數(shù)據(jù)庫(kù)中找
mCounties = LitePal.where("cityid=?",String.valueOf(mCurrentCity.getId())).find(County.class);
if (mCounties.size()!=0){
mListData.clear();
for (County county:mCounties){
mListData.add(county.getCountyName());
}
mAdapter.notifyDataSetChanged();
currentPage = CURRENT_PAGE_COUNTY;
}else {
int provinceCode = mCurrentProvince.getProvinceCode();
int citiCode = mCurrentCity.getCityCode();
String url = "http://guolin.tech/api/china/" + provinceCode+"/"+citiCode;
queryFromServer(url,CURRENT_PAGE_COUNTY);
}
}
private void queryCities() {
titleTV.setText(mCurrentProvince.getProvinceName());
backBtn.setVisibility(View.VISIBLE);
// 從數(shù)據(jù)庫(kù)中找
mCities = LitePal.where("provinceid=?",String.valueOf(mCurrentProvince.getId())).find(City.class);
if (mCities.size()!=0){
mListData.clear();
for (City city:mCities){
mListData.add(city.getCityName());
}
mAdapter.notifyDataSetChanged();
currentPage = CURRENT_PAGE_CITY;
}else {
int provinceCode = mCurrentProvince.getProvinceCode();
String url = "http://guolin.tech/api/china/" + provinceCode;
queryFromServer(url,CURRENT_PAGE_CITY);
}
}
/**
* 顯示進(jìn)度對(duì)話(huà)框
*/
private void showProgressDialog() {
if (progressDialog == null) {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("正在加載...");
progressDialog.setCanceledOnTouchOutside(false);
}
progressDialog.show();
}
/**
* 關(guān)閉進(jìn)度對(duì)話(huà)框
*/
private void closeProgressDialog() {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
}
?Utility :
package com.example.okhttpdemo;
import android.text.TextUtils;
import com.example.okhttpdemo.Bean.City;
import com.example.okhttpdemo.Bean.County;
import com.example.okhttpdemo.Bean.Province;
import com.google.gson.Gson;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Utility {
/**
* 解析和處理服務(wù)器返回的省級(jí)的數(shù)據(jù)
*/
public static boolean handleProvinceResponse(String response) {
if (!TextUtils.isEmpty(response)) {
try {
JSONArray allProvinces = new JSONArray(response);
for (int i = 0; i < allProvinces.length(); i++) {
JSONObject provinceObject = allProvinces.getJSONObject(i);
Province province = new Province();
province.setProvinceName(provinceObject.getString("name"));
province.setProvinceCode(provinceObject.getInt("id"));
province.save();
}
return true;
} catch (JSONException e) {
e.printStackTrace();
}
}
return false;
}
/**
* 解析和處理服務(wù)器返回的市級(jí)的數(shù)據(jù)
*/
public static boolean handleCitiesResponse(String response,int provinceId){
if (!TextUtils.isEmpty(response)){
try {
JSONArray allCities = new JSONArray(response);
for (int i = 0; i < allCities.length() ; i++) {
JSONObject cityObject = allCities.getJSONObject(i);
City city = new City();
city.setCityName(cityObject.getString("name"));
city.setCityCode(cityObject.getInt("id"));
city.setProvinceId(provinceId);
city.save();
}
return true;
} catch (JSONException e) {
e.printStackTrace();
}
}
return false;
}
/**
* 解析和處理服務(wù)器返回的縣級(jí)的數(shù)據(jù)
*/
public static boolean handleCountyResponse(String response,int cityId){
if (!TextUtils.isEmpty(response)){
try {
JSONArray allCounties = new JSONArray(response);
for (int i = 0; i < allCounties.length() ; i++) {
JSONObject countryObject = allCounties.getJSONObject(i);
County country = new County();
country.setCountyName(countryObject.getString("name"));
country.setWeatherId(countryObject.getString("weather_id"));
country.setCityId(cityId);
country .save();
}
return true;
} catch (JSONException e) {
e.printStackTrace();
}
}
return false;
}
}
?HttpTool :
package com.example.okhttpdemo;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class HttpTool {
/**
*
* @param address 接口地址URL
* @param callback
*/
public static void sendOkhttpRequest(String address,okhttp3.Callback callback){
// 1、創(chuàng)建OkHttpClient對(duì)象
OkHttpClient client = new OkHttpClient();
// 2、創(chuàng)建Request對(duì)象
Request request = new Request.Builder().url(address).build();
// 3、發(fā)送異步請(qǐng)求
client.newCall(request).enqueue(callback);
}
}
Province :?
package com.example.okhttpdemo.Bean;
import org.litepal.crud.LitePalSupport;
public class Province extends LitePalSupport {
private int id;
private String provinceName;
private int provinceCode;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getProvinceName() {
return provinceName;
}
public void setProvinceName(String provinceName) {
this.provinceName = provinceName;
}
public int getProvinceCode() {
return provinceCode;
}
public void setProvinceCode(int provinceCode) {
this.provinceCode = provinceCode;
}
}
?City:
package com.example.okhttpdemo.Bean;
import org.litepal.crud.LitePalSupport;
public class City extends LitePalSupport {
private int id;
private String cityName;
private int cityCode;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public int getCityCode() {
return cityCode;
}
public void setCityCode(int cityCode) {
this.cityCode = cityCode;
}
public int getProvinceId() {
return provinceId;
}
public void setProvinceId(int provinceId) {
this.provinceId = provinceId;
}
private int provinceId;
}
County :?
package com.example.okhttpdemo.Bean;
import org.litepal.crud.LitePalSupport;
public class County extends LitePalSupport {
private int id;
private String countyName;
private String weatherId;
private int cityId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCountyName() {
return countyName;
}
public void setCountyName(String countyName) {
this.countyName = countyName;
}
public String getWeatherId() {
return weatherId;
}
public void setWeatherId(String weatherId) {
this.weatherId = weatherId;
}
public int getCityId() {
return cityId;
}
public void setCityId(int cityId) {
this.cityId = cityId;
}
}
activity_main:?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#7283DD"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/teal_200">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/title_text"
android:layout_centerInParent="true"
android:textColor="#fff"
android:textSize="20sp"/>
<Button
android:id="@+id/back_button"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginLeft="10dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@drawable/back"
/>
</RelativeLayout>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
litepal.xml:?
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value = "okhttpdemo"/>
<version value = "1"/>
<list>
<mapping class = "com.example.okhttpdemo.Bean.Province"/>
<mapping class = "com.example.okhttpdemo.Bean.City"/>
<mapping class = "com.example.okhttpdemo.Bean.County"/>
</list>
</litepal>
AndroidManifest:?
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.okhttpdemo">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:networkSecurityConfig="@xml/network_security_config"
android:name = "org.litepal.LitePalApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
依賴(lài):?
implementation("com.squareup.okhttp3:okhttp:3.4.1")
implementation 'org.litepal.guolindev:core:3.2.3'
implementation 'com.google.code.gson:gson:2.7'
運(yùn)行結(jié)果:
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-653336.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-653336.html
到了這里,關(guān)于安卓:網(wǎng)絡(luò)框架okhttp的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!