連線到網路
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
如要在應用程式中執行網路作業,資訊清單必須包含下列權限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
安全網路通訊的最佳做法
將網路功能加入應用程式前,您需要確保應用程式內的資料和資訊在透過網路傳輸時安全無虞。如要這麼做的話,請按照下列網路安全性最佳做法操作:
- 請盡量減少透過網路傳輸機密或個人使用者資料。
- 應用程式透過 SSL,傳送到所有網絡。
- 建議您建立網路安全性設定,讓應用程式信任自訂憑證授權單位 (CA),或限制可信任通訊的 CA 系統組合。
如要進一步瞭解如何套用安全網路的原則,請參閱網路安全性提示。
選擇 HTTP 用戶端
大多數具備網路連線的應用程式會使用 HTTP 傳送及接收資料。Android 平台包括 HttpsURLConnection
用戶端,其支援傳輸層安全標準 (TLS)、串流上傳和下載、可設定逾時、IPv6 和連線集區。
此外,某些第三方程式庫也提供更高階的網路作業 API。這些 API 可支援各種便利功能,例如將要求主體序列化,以及將回應主體反序列化。
- Retrofit:這個類型安全的 HTTP 用戶端適用於 Square 的 JVM,以 OkHttp 為建構基礎。Retrofit 可讓您以宣告方式建立用戶端介面,同時支援多個序列化程式庫。
- Ktor:這個 JetBrains 的 HTTP 用戶端全為 Kotlin 建構而成,採用協同程式提供的技術。Ktor 支援各種引擎、序列化程式和平台。
解析 DNS 查詢
搭載 Android 10 (API 級別 29) 以上版本的裝置內建支援功能,可同時透過明文查詢和「透過 TLS 執行 DNS」模式專門處理 DNS 查詢。DnsResolver
API 提供一般的非同步解析,可讓您查詢 SRV
、NAPTR
和其他記錄類型。請注意,剖析回應會留在應用程式中執行。
在搭載 Android 9 (API 級別 28) 或以下版本的裝置上,平台 DNS 解析器僅支援 A
和 AAAA
記錄。這可讓您查詢與名稱相關聯的 IP 位址,但不支援任何其他記錄類型。
如需以 NDK 為基礎的應用程式,請參閱 android_res_nsend
的說明。
使用存放區封裝網路作業
如要簡化執行網路作業的流程,並減少應用程式中各部分的程式碼重複,您可以使用存放區設計模板。存放區是一種資料處理作業的類別,也是針對某些特定資料或資源提供簡潔的 API 抽象層。
您可以使用 Retrofit 宣告介面,指定網路作業的 HTTP 方法、網址、引數和回應類型,如以下範例所示:
Kotlin
interface UserService {
@GET("/users/{id}")
suspend fun getUser(@Path("id") id: String): User
}
Java
public interface UserService {
@GET("/user/{id}")
Call<User> getUserById(@Path("id") String id);
}
在存放區類別中,函式可以封裝網路作業並公開結果。這個封裝可確保呼叫存放區的元件,並不需要知道資料的儲存方式。日後若資料儲存方式有所變更,也都只會侷限在存放區類別之中。舉例來說,您可能會想進行遠端變更 (例如更新 API 端點),或是想要導入本機快取,這些都屬於上述情況。
Kotlin
class UserRepository constructor(
private val userService: UserService
) {
suspend fun getUserById(id: String): User {
return userService.getUser(id)
}
}
Java
class UserRepository {
private UserService userService;
public UserRepository(
UserService userService
) {
this.userService = userService;
}
public Call<User> getUserById(String id) {
return userService.getUser(id);
}
}
為了避免建立沒有回應的 UI,請勿在主執行緒中執行網路作業。根據預設,Android 會要求您在主 UI 執行緒以外的執行緒上執行網路作業。如果您嘗試在主執行緒上執行網路作業,系統會擲回 NetworkOnMainThreadException
。
在上一個程式碼範例中,系統實際上並未觸發網路作業。UserRepository
的呼叫者必須使用協同程式或 enqueue()
函式來實作執行緒。詳情請參閱「從網際網路取得資料」程式碼研究室,瞭解如何使用 Kotlin 協同程式實作執行緒。
在設定變更後仍然有效
發生設定變更 (例如畫面旋轉) 時,系統會刪除您的片段或活動,再重新建立工作。由於片段活動的實例狀態中只能儲存少量資料,因此任何未儲存的資料都會遺失。如果發生這種情況,您可能需要再次發出網路要求。
您可以使用 ViewModel
,確保資料在設定變更後仍然有效。ViewModel
元件的設計可讓您以注重生命週期的方式儲存及管理 UI 相關資料。如果您使用上述 UserRepository
,ViewModel
即可發出必要的網路要求,並使用 LiveData
將結果提供給片段或活動:
Kotlin
class MainViewModel constructor(
savedStateHandle: SavedStateHandle,
userRepository: UserRepository
) : ViewModel() {
private val userId: String = savedStateHandle["uid"] ?:
throw IllegalArgumentException("Missing user ID")
private val _user = MutableLiveData<User>()
val user = _user as LiveData<User>
init {
viewModelScope.launch {
try {
// Calling the repository is safe as it moves execution off
// the main thread
val user = userRepository.getUserById(userId)
_user.value = user
} catch (error: Exception) {
// Show error message to user
}
}
}
}
Java
class MainViewModel extends ViewModel {
private final MutableLiveData<User> _user = new MutableLiveData<>();
LiveData<User> user = (LiveData<User>) _user;
public MainViewModel(
SavedStateHandle savedStateHandle,
UserRepository userRepository
) {
String userId = savedStateHandle.get("uid");
Call<User> userCall = userRepository.getUserById(userId);
userCall.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
_user.setValue(response.body());
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
// Show error message to user
}
});
}
}
如要進一步瞭解這個主題,請參閱下列相關指南:
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-08-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-08-27 (世界標準時間)。"],[],[],null,["To perform network operations in your application, your manifest must include\nthe following permissions: \n\n \u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\n \u003cuses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" /\u003e\n\n| **Note:** Both the [`INTERNET`](/reference/android/Manifest.permission#INTERNET) and [`ACCESS_NETWORK_STATE`](/reference/android/Manifest.permission#ACCESS_NETWORK_STATE) permissions are [normal\n| permissions](/develop/permissions/overview#normal-dangerous), which means they're granted at install time and don't need to be [requested at runtime](/training/permissions/requesting).\n\nBest practices for secure network communication\n\nBefore you add networking functionality to your app, you need to ensure that\ndata and information within your app stay safe when you are transmitting over a\nnetwork. To do so, follow these networking security best practices:\n\n- Minimize the amount of sensitive or personal [user\n data](/privacy-and-security/security-tips#user-data) that you transmit over the network.\n- Send all network traffic from your app over [SSL](/training/articles/security-ssl).\n- Consider creating a [network security\n configuration](/training/articles/security-config), which lets your app trust custom certificate authorities (CAs) or restrict the set of system CAs that it trusts for secure communication.\n\nFor more information on how to apply secure networking principles, see the\n[networking security tips](/privacy-and-security/security-tips#networking).\n\nChoose an HTTP client\n\nMost network-connected apps use HTTP to send and receive data. The Android\nplatform includes the\n[`HttpsURLConnection`](/reference/javax/net/ssl/HttpsURLConnection) client,\nwhich supports TLS, streaming uploads and downloads, configurable timeouts,\nIPv6, and connection pooling.\n\nThird-party libraries that offer higher-level APIs for networking operations are\nalso available. These support various convenience features, such as the\nserialization of request bodies and deserialization of response bodies.\n\n- [Retrofit](https://square.github.io/retrofit/): a type-safe HTTP client for the JVM from Square, built on top of OkHttp. Retrofit lets you create a client interface declaratively and has support for several serialization libraries.\n- [Ktor](https://ktor.io/): an HTTP client from JetBrains, built entirely for Kotlin and powered by coroutines. Ktor supports various engines, serializers, and platforms.\n\nResolve DNS queries\n\nDevices that run Android 10 (API level 29) and higher have built-in support for\nspecialized DNS lookups through both cleartext lookups and DNS-over-TLS mode.\nThe [`DnsResolver`](/reference/android/net/DnsResolver) API provides generic,\nasynchronous resolution, which lets you look up `SRV`, `NAPTR`, and other\nrecord types. Parsing the response is left to the app to perform.\n\nOn devices that run Android 9 (API level 28) and lower, the platform DNS\nresolver supports only `A` and `AAAA` records. This lets you look up the IP\naddresses associated with a name but doesn't support any other record types.\n\nFor NDK-based apps, see\n[`android_res_nsend`](/ndk/reference/group/networking#android_res_nsend).\n\nEncapsulate network operations with a repository\n\nTo simplify the process of performing network operations and reduce code\nduplication in various parts of your app, you can use the repository design\npattern. A repository is a class that handles data operations and provides a\nclean API abstraction over some specific data or resource.\n\nYou can use Retrofit to declare an interface that specifies the HTTP method,\nURL, arguments, and response type for network operations, as in the following\nexample: \n\nKotlin \n\n```kotlin\ninterface UserService {\n @GET(\"/users/{id}\")\n suspend fun getUser(@Path(\"id\") id: String): User\n}\n```\n\nJava \n\n```java\npublic interface UserService {\n @GET(\"/user/{id}\")\n Call\u003cUser\u003e getUserById(@Path(\"id\") String id);\n}\n```\n\nWithin a repository class, functions can encapsulate network operations and\nexpose their results. This encapsulation ensures that the components that call\nthe repository don't need to know how the data is stored. Any future changes to\nhow the data is stored are isolated to the repository class as well. For\nexample, you might have a remote change such as an update to API endpoints, or\nyou might want to implement local caching. \n\nKotlin \n\n```kotlin\nclass UserRepository constructor(\n private val userService: UserService\n) {\n suspend fun getUserById(id: String): User {\n return userService.getUser(id)\n }\n}\n```\n\nJava \n\n```java\nclass UserRepository {\n private UserService userService;\n\n public UserRepository(\n UserService userService\n ) {\n this.userService = userService;\n }\n\n public Call\u003cUser\u003e getUserById(String id) {\n return userService.getUser(id);\n }\n}\n```\n\nTo avoid creating an unresponsive UI, don't perform network operations on the\nmain thread. By default, Android requires you to perform network operations on a\nthread other than the main UI thread. If you try to perform network operations\non the main thread, a\n[`NetworkOnMainThreadException`](/reference/android/os/NetworkOnMainThreadException)\nis thrown.\n\nIn the previous code example, the\nnetwork operation isn't actually triggered. The caller of the `UserRepository`\nmust implement the threading either using coroutines or using the `enqueue()`\nfunction. For more information, see the codelab [Get data from the\ninternet](/codelabs/basic-android-kotlin-training-getting-data-internet),\nwhich demonstrates how to implement threading using Kotlin coroutines.\n\nSurvive configuration changes\n\nWhen a configuration change occurs, such as a screen rotation, your fragment or\nactivity is destroyed and recreated. Any data not saved in the instance\nstate for your fragment activity, which can only hold small amounts of data,\nis lost. If this occurs, you might need to make your network requests again.\n\nYou can use a [`ViewModel`](/topic/libraries/architecture/viewmodel) to let\nyour data survive configuration changes. The `ViewModel` component is\ndesigned to store and manage UI-related data in a lifecycle-conscious\nway. Using the preceding `UserRepository`, the `ViewModel` can make the\nnecessary network requests and provide the result to your fragment or activity\nusing [`LiveData`](/topic/libraries/architecture/livedata): \n\nKotlin \n\n```kotlin\nclass MainViewModel constructor(\n savedStateHandle: SavedStateHandle,\n userRepository: UserRepository\n) : ViewModel() {\n private val userId: String = savedStateHandle[\"uid\"] ?:\n throw IllegalArgumentException(\"Missing user ID\")\n\n private val _user = MutableLiveData\u003cUser\u003e()\n val user = _user as LiveData\u003cUser\u003e\n\n init {\n viewModelScope.launch {\n try {\n // Calling the repository is safe as it moves execution off\n // the main thread\n val user = userRepository.getUserById(userId)\n _user.value = user\n } catch (error: Exception) {\n // Show error message to user\n }\n\n }\n }\n}\n```\n\nJava \n\n```java\nclass MainViewModel extends ViewModel {\n\n private final MutableLiveData\u003cUser\u003e _user = new MutableLiveData\u003c\u003e();\n LiveData\u003cUser\u003e user = (LiveData\u003cUser\u003e) _user;\n\n public MainViewModel(\n SavedStateHandle savedStateHandle,\n UserRepository userRepository\n ) {\n String userId = savedStateHandle.get(\"uid\");\n Call\u003cUser\u003e userCall = userRepository.getUserById(userId);\n userCall.enqueue(new Callback\u003cUser\u003e() {\n @Override\n public void onResponse(Call\u003cUser\u003e call, Response\u003cUser\u003e response) {\n if (response.isSuccessful()) {\n _user.setValue(response.body());\n }\n }\n\n @Override\n public void onFailure(Call\u003cUser\u003e call, Throwable t) {\n // Show error message to user\n }\n });\n }\n}\n```\n\nRead related guides\n\nTo learn more about this topic, see the following related guides:\n\n- [Reduce network battery drain: Overview](/topic/performance/power)\n- [Minimize the effect of regular updates](/training/efficient-downloads)\n- [Web-based content](/guide/webapps)\n- [Application fundamentals](/guide/components/fundamentals)\n- [Guide to app architecture](/jetpack/guide)"]]