Android-網(wǎng)絡(luò)請(qǐng)求

1. OkHttp

OkHttp是由 Square 公司開發(fā)的一個(gè) HTTP 客戶端庫(kù),用于在 Java 和 Android 中執(zhí)行網(wǎng)絡(luò)請(qǐng)求。它功能強(qiáng)大斗搞、性能高效指攒,并且支持各種高級(jí)特性,如連接池僻焚、請(qǐng)求緩存允悦、攔截器等。采用OkHttp進(jìn)行簡(jiǎn)單的getpost請(qǐng)求示例:

object BoxHttp {
    private const val BASEURL = "https://api.mocation.cc/api"

    private val client: OkHttpClient = OkHttpClient.Builder()
        .connectTimeout(5, TimeUnit.SECONDS)
        .readTimeout(5, TimeUnit.SECONDS)
        .writeTimeout(5, TimeUnit.SECONDS)
//        .addInterceptor(LoggingInterceptor())
        .build()

    /**
     * 同步GET方法
     */
    fun getSync() {
        Thread(kotlinx.coroutines.Runnable {
            val request: Request = Request.Builder()
                .url("${BASEURL}/coopen/data")
                .build()
            val call = client.newCall(request)
            val response = call.execute()

            val body = response.body?.string()
            Log.e("okhttp", "收到了返回值:$body")
        }).start()
    }

    /**
     * 異步GET方法
     */
    fun getAsync() {
        val request = Request.Builder()
            .url("https://api.mocation.cc/api/coopen/data")
            .build()
        Log.e("okhttp", "收到了 連接:${request.url}")
        val call = client.newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                Log.e("okhttp", "收到了 異步 錯(cuò)誤返回值:${e.message}")
            }

            override fun onResponse(call: Call, response: Response) {
                Log.e("okhttp", "收到了異步 返回值:${response.body?.string()}")
            }

        })
    }

    /**
     * 同步POST方法
     */
    fun postSync() {
        Thread(kotlinx.coroutines.Runnable {
            val body: FormBody = FormBody.Builder()
                .build()
            val request: Request = Request.Builder()
                .url("${BASEURL}/article/23/like")
                .post(body)
                .build()
            val call = client.newCall(request)
            val response = call.execute()

            val bodyR = response.body?.string()
            Log.e("okhttp", "POST 收到了返回值:$bodyR")
        }).start()
    }

    /**
     * 異步POST方法
     */
    fun postAsync() {
        Log.e("okhttp","當(dāng)前線程2:${Thread.currentThread()}")
        val body: FormBody = FormBody.Builder()
            .build()

        val httpUrl = "${BASEURL}/article/23/like"
        Log.e("okhttp", "請(qǐng)求的Url:$httpUrl")

        val request: Request = Request.Builder()
            .url(httpUrl)
            .post(body)
            .build()
        val call = client.newCall(request)

        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                Log.e("okhttp","當(dāng)前線程3:${Thread.currentThread()}")
                Log.e("okhttp", "收到了 POST 異步 錯(cuò)誤返回值:${e.message}")
            }
            override fun onResponse(call: Call, response: Response) {
                Log.e("okhttp","當(dāng)前線程3:${Thread.currentThread()}")
                Log.e("okhttp", "收到了 POST 異步 返回值:${response.body?.string()}")
            }
        })
    }
}

在OkHttp中提供了強(qiáng)大的攔截器Interceptor,我們可以在自定義的Interceptor中虑啤,對(duì)請(qǐng)求進(jìn)行修改或者對(duì)返回體進(jìn)行統(tǒng)一的一些處理隙弛,比如要在請(qǐng)求頭中添加通用的請(qǐng)求頭或者在返回體中進(jìn)行特殊錯(cuò)誤的判斷等

class LoggingInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val time_start = System.nanoTime()
        val request = chain.request()

        // 修改請(qǐng)求,添加新的請(qǐng)求頭
        val newRequest = request.newBuilder()
            .addHeader("User-Agent", "Mocation/1.0.0/234/iOS/18.1.1")               // 添加另一個(gè)請(qǐng)求頭
            .build()

        val response = chain.proceed(newRequest)

        val buffer = Buffer()
        request.body?.writeTo(buffer)
        val requestBodyStr = buffer.readUtf8()
        Log.e(
            "okhttp",
            String.format(
                "發(fā)送請(qǐng)求:%s 參數(shù):%s",
                request.url,
                requestBodyStr
            )
        )

        val responseStr = response.body?.string() ?: "空返回" //response.body?.string() 在請(qǐng)求中只能調(diào)用一次,所以再返回的時(shí)候要新建一個(gè)response來(lái)返回

        val mediaType = response.body?.contentType()
        val newBody = ResponseBody.create(mediaType, responseStr)
        val newResponse = response.newBuilder().body(newBody).build()

        val time_end = System.nanoTime()

        Log.e(
            "okhttp",
            String.format("拿到返回:%s  時(shí)間:%.1fms", request.url, (time_end - time_start) / 1e6)
        )

        return newResponse
    }

}

這樣自定義后狞山,在OkHttpClient的Builder()后面再追加上.addInterceptor(LoggingInterceptor())全闷,便會(huì)執(zhí)行到我們自定義的攔截器方法里。

2. gson

Gson是由 Google 開發(fā)的一個(gè)用于 Java 和 Kotlin 的 JSON 數(shù)據(jù)解析庫(kù)萍启,用于在對(duì)象和 JSON 字符串之間進(jìn)行序列化和反序列化总珠。它功能強(qiáng)大且易于使用,在 Android 開發(fā)中非常常見(jiàn)勘纯。開發(fā)中會(huì)經(jīng)常使用Json和自定義對(duì)象的互相轉(zhuǎn)換局服,首先要在工程中添加對(duì)gson的依賴:

implementation(libs.gson)

使用的基本方法如下:

fun main() {
    val gson = Gson()
    val userStr = "{\"uid\":123,\"nickName\":\"甲方\"}"
    val user = gson.fromJson<User>(userStr,User::class.java)
    println("用戶昵稱:${user.nickName}")
    println("用戶信息:${user.toString()}")

    val userString = gson.toJson(user)
    println("用戶字符串:${userString}")

    val userArrStr = "[{\"uid\":123,\"nickName\":\"甲方\"},{\"uid\":234,\"nickName\":\"乙方\"}]"
    val userList:List<User> = gson.fromJson(userArrStr, object :TypeToken<List<User>>(){}.type)
    println("用戶數(shù)組:${userList}")
    val userListString = gson.toJson(userList)
    println("用戶數(shù)組字符串:${userListString}")

}

class User {
    var uid:Int = 0
    var nickName = ""
    override fun toString(): String {
        return "User(uid=$uid, nickName='$nickName')"
    }
}

這里可以有一個(gè)方便的Android Studio插件,JsonToKotlinClass可以方便的將json字符串轉(zhuǎn)換為Kotlin中的對(duì)象驳遵。

3. Retrofit

Retrofit是由 Square 公司開發(fā)的一個(gè)功能強(qiáng)大的 網(wǎng)絡(luò)請(qǐng)求庫(kù)淫奔,用于在 Android 開發(fā)中進(jìn)行 HTTP 網(wǎng)絡(luò)通信。它提供了簡(jiǎn)單且可擴(kuò)展的 API超埋,極大地簡(jiǎn)化了網(wǎng)絡(luò)請(qǐng)求的編寫,使得代碼更加簡(jiǎn)潔佳鳖、可維護(hù)霍殴。
簡(jiǎn)單的實(shí)現(xiàn)一個(gè)get請(qǐng)求:

object BoxRetrofit {
    private const val BASEURL = "https://api.mocation.cc/api/"
    val apiService: ApiService by lazy {
        Retrofit.Builder()
            .baseUrl(BASEURL) // 基礎(chǔ) URL
            .addConverterFactory(GsonConverterFactory.create()) // Gson 轉(zhuǎn)換器
            .build()
            .create(ApiService::class.java)
    }
}
interface ApiService {
    @GET(value = "coopen/data")
    fun queryNumberInfo():Call<IndexResponse>
}
data class IndexResponse(
    val code: Int,
    val data: CountInfo,
    val msg: Any
)
data class CountInfo(
    val movieCount: Int,
    val placeCount: Int
)

Retrofit.Builder()后面也可以跟上自己的client設(shè)置自定義的OkHttpClient,這樣就可以添加自己的攔截器進(jìn)行各種操作。
在Activity中就可以這么請(qǐng)求數(shù)據(jù):

BoxRetrofit.apiService.queryNumberInfo().enqueue(object :retrofit2.Callback<IndexResponse> {
     override fun onResponse(call: Call<IndexResponse>, response: Response<IndexResponse>) {
        Log.e("retrofit", "收到了 異步 返回值:${response.body()?.data?.movieCount}")
     }
     override fun onFailure(call: Call<IndexResponse>, t: Throwable) {
          Log.e("retrofit", "收到了 異步 錯(cuò)誤返回值:${t.message}")
     }
})
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末系吩,一起剝皮案震驚了整個(gè)濱河市来庭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌穿挨,老刑警劉巖月弛,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異科盛,居然都是意外死亡帽衙,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門贞绵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)厉萝,“玉大人,你說(shuō)我怎么就攤上這事∏吹妫” “怎么了章母?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)翩剪。 經(jīng)常有香客問(wèn)我乳怎,道長(zhǎng),這世上最難降的妖魔是什么前弯? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任蚪缀,我火速辦了婚禮,結(jié)果婚禮上博杖,老公的妹妹穿的比我還像新娘椿胯。我一直安慰自己,他們只是感情好剃根,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布哩盲。 她就那樣靜靜地躺著,像睡著了一般狈醉。 火紅的嫁衣襯著肌膚如雪廉油。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天苗傅,我揣著相機(jī)與錄音抒线,去河邊找鬼。 笑死渣慕,一個(gè)胖子當(dāng)著我的面吹牛嘶炭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逊桦,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼眨猎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了强经?” 一聲冷哼從身側(cè)響起睡陪,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匿情,沒(méi)想到半個(gè)月后兰迫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炬称,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年汁果,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玲躯。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡须鼎,死狀恐怖鲸伴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晋控,我是刑警寧澤汞窗,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站赡译,受9級(jí)特大地震影響仲吏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蝌焚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一裹唆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧只洒,春花似錦许帐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至涝开,卻和暖如春循帐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舀武。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工拄养, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人银舱。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓瘪匿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親寻馏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棋弥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容