Android 开发中网络编程是实现应用与服务端数据交互的核心能力,随着 Android 生态的发展,网络请求方式从早期的 HttpURLConnection 逐步演进到 OkHttp,再到封装性更强的 Retrofit,数据解析也从 XML 为主转向 JSON 为主
Android 规定主线程(UI 线程)不能执行耗时操作(网络请求属于耗时操作),否则会触发 ANR(应用无响应),因此网络请求需在子线程执行,同时需解决子线程与主线程的通信问题
WebView
WebView 是 Android 中用于在应用内展示网页内容的核心控件,相比跳转系统浏览器,使用 WebView 能更好地保持应用体验的一致性。
基本示例如下
1 2 3 4 5 6 <?xml version="1.0" encoding="utf-8" ?> <WebView xmlns:android ="http://schemas.android.com/apk/res/android" android:id ="@+id/webView" android:layout_width ="match_parent" android:layout_height ="match_parent" />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import android.os.Bundleimport android.webkit.WebSettingsimport android.webkit.WebViewimport android.webkit.WebViewClientimport androidx.appcompat.app.AppCompatActivityclass WebViewActivity : AppCompatActivity () { private lateinit var webView: WebView override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_webview) webView = findViewById(R.id.webView) initWebView() webView.loadUrl("https://github.com" ) } private fun initWebView () { val webSettings = webView.settings webSettings.javaScriptEnabled = true webView.webViewClient = WebViewClient() } override fun onBackPressed () { if (webView.canGoBack()) webView.goBack() else super .onBackPressed() } override fun onDestroy () { webView.destroy() super .onDestroy() } }
HttpURLConnection
HttpURLConnection 是 Android 原生的网络请求 API,虽功能基础但无需依赖第三方库,是理解网络请求原理的基础,该方式现已逐步被 OkHttp 替代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.net.HttpURLConnectionimport java.net.URLimport java.io.BufferedReaderimport java.io.InputStreamReaderfun sendGetRequest (urlString: String ) { Thread { var connection: HttpURLConnection? = null try { val url = URL(urlString) connection = url.openConnection() as HttpURLConnection connection.requestMethod = "GET" connection.connectTimeout = 5000 connection.readTimeout = 5000 if (connection.responseCode == HttpURLConnection.HTTP_OK) { val inputStream = connection.inputStream val reader = BufferedReader(InputStreamReader(inputStream)) val response = StringBuilder() var line: String? while (reader.readLine().also { line = it } != null ) { response.append(line) } reader.close() inputStream.close() val result = response.toString() } } catch (e: Exception) { e.printStackTrace() } finally { connection?.disconnect() } }.start() }
OkHttp
OkHttp 是 Square 公司开发的轻量级网络框架,解决了 HttpURLConnection 的诸多痛点(如连接池、自动重试、拦截器等),是当前 Android 网络请求的基础组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import okhttp3.*import java.io.IOExceptionfun getRequest (url: String ) { val client = OkHttpClient() val request = Request.Builder() .url(url) .build() client.newCall(request).enqueue(object : Callback { override fun onFailure (call: Call , e: IOException ) { e.printStackTrace() } override fun onResponse (call: Call , response: Response ) { val result = response.body?.string() } }) } fun postRequest (url: String ) { val client = OkHttpClient() val requestBody = FormBody.Builder() .add("key1" , "value1" ) .add("key2" , "value2" ) .build() val request = Request.Builder() .url(url) .post(requestBody) .build() client.newCall(request).enqueue(object : Callback { override fun onFailure (call: Call , e: IOException ) { e.printStackTrace() } override fun onResponse (call: Call , response: Response ) { val result = response.body?.string() } }) }
JSON 解析
JSONObject
通过 JSONObject 的 getString()、getInt() 等方法手动解析 JSON 字符串,适合简单结构的 JSON 数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import org.json.JSONObjectfun parseJsonWithJSONObject (jsonStr: String ) { val jsonObject = JSONObject(jsonStr) val id = jsonObject.getInt("id" ) val name = jsonObject.getString("name" ) val type = jsonObject.getString("type" ) val isFree = jsonObject.getBoolean("isFree" ) val readCount = jsonObject.getInt("readCount" ) val result = "ID:$id ,名称:$name ,类型:$type ,是否免费:$isFree ,阅读量:$readCount " }
GSON
Google 推出的 JSON 解析库,通过 gson.fromJson(jsonStr, TargetClass.class) 可自动将 JSON 字符串解析为指定实体类对象,支持复杂嵌套结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import com.google.gson.Gsondata class Course ( val id: Int , val name: String, val type: String, val isFree: Boolean , val readCount: Int ) fun parseJsonWithGson (jsonStr: String ) { val gson = Gson() val course = gson.fromJson(jsonStr, Course::class .java) val result = "课程:${course.name} ,阅读量:${course.readCount} " }
Retrofit
Retrofit 是基于 OkHttp 的封装型网络框架,通过注解化配置简化接口定义,支持多种数据解析器和适配器,是当前 Android 网络开发的首选方案
接口定义
Retrofit 使用注解配置接口定义
基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import com.google.gson.annotations.SerializedNameimport retrofit2.Responseimport retrofit2.Retrofitimport retrofit2.converter.gson.GsonConverterFactoryimport retrofit2.adapter.rxjava3.RxJava3CallAdapterFactoryimport retrofit2.http.GETimport retrofit2.http.Pathimport retrofit2.http.Queryimport kotlinx.coroutines.runBlockingdata class Article ( val id: Int , val title: String ) data class ArticleResponse ( val code: Int , @SerializedName("data" ) val articleList: List<Article> ) interface ApiService { @GET("article/list/{page}" ) suspend fun getArticleList ( @Path("page" ) page: Int , @Query("size" ) pageSize: Int ) : Response<ArticleResponse>} fun main () = runBlocking { val retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/" ) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .build() val apiService = retrofit.create(ApiService::class .java) val response = apiService.getArticleList(page = 1 , pageSize = 10 ) if (response.isSuccessful) { val articles = response.body()?.articleList } }