| 
 | 
 
在Android开发中,android.os.NetworkOnMainThreadException异常通常发生在主线程(UI线程)上执行网络操作时。为了避免这个异常,我们应该在后台线程中执行网络请求或其他耗时操作。在Kotlin协程(Coroutine)的帮助下,我们可以轻松地在后台线程中执行这些任务,而不会阻塞主线程,并在任务完成后安全地更新UI。 
下面是一个使用Kotlin协程来执行网络请求并避免NetworkOnMainThreadException的示例: 
1. 添加依赖 
首先,确保你的build.gradle文件中包含了Kotlin协程的依赖:- dependencies {
 
 -     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:x.y.z" // 使用最新版本
 
 -     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:x.y.z" // 通常也会包含核心库
 
 -     // 其他依赖...
 
 - }
 
 
  复制代码 2. 创建网络请求函数 
创建一个封装了网络请求的函数。这个函数应该使用协程的withContext函数来在IO调度器上执行网络操作。 
 
- import kotlinx.coroutines.withContext
 
 - import kotlinx.coroutines.Dispatchers
 
 - import kotlin.coroutines.CoroutineContext
 
  
- suspend fun fetchDataFromNetwork(url: String, context: CoroutineContext = Dispatchers.Main): String {
 
 -     return withContext(Dispatchers.IO) { // 切换到IO调度器
 
 -         // 这里应该是实际的网络请求代码,比如使用OkHttp或Retrofit
 
 -         // 但为了简单起见,我们模拟一个网络请求
 
 -         delay(2000) // 模拟网络延迟
 
 -         "Data from $url" // 假设这是从网络获取的数据
 
 -     }
 
 - }
 
 
  复制代码 注意:在实际应用中,你应该使用像Retrofit这样的网络库来处理HTTP请求,而不是使用delay函数。 
3. 在ViewModel中使用协程 
在你的ViewModel中,使用viewModelScope来启动一个协程,并调用你的网络请求函数。 
 
- import androidx.lifecycle.LiveData
 
 - import androidx.lifecycle.MutableLiveData
 
 - import androidx.lifecycle.ViewModel
 
 - import kotlinx.coroutines.launch
 
  
- class MyViewModel : ViewModel() {
 
 -     private val _networkData = MutableLiveData<String?>()
 
 -     val networkData: LiveData<String?> get() = _networkData
 
  
-     fun loadDataFromNetwork(url: String) {
 
 -         viewModelScope.launch { // 使用viewModelScope来启动协程
 
 -             try {
 
 -                 val data = fetchDataFromNetwork(url) // 调用网络请求函数
 
 -                 _networkData.value = data // 更新LiveData
 
 -             } catch (e: Exception) {
 
 -                 // 处理异常,比如显示错误消息
 
 -                 _networkData.value = "Error: ${e.message}"
 
 -             }
 
 -         }
 
 -     }
 
 - }
 
 
  复制代码 4. 在Activity或Fragment中观察LiveData 
在你的Activity或Fragment中,观察ViewModel中的LiveData,并在数据变化时更新UI。 
 
- import androidx.activity.viewModels
 
 - import androidx.fragment.app.Fragment
 
 - import androidx.lifecycle.Observer
 
 - import android.os.Bundle
 
 - import android.view.LayoutInflater
 
 - import android.view.View
 
 - import android.view.ViewGroup
 
 - import android.widget.TextView
 
  
- class MyFragment : Fragment() {
 
 -     private val myViewModel: MyViewModel by viewModels()
 
  
-     override fun onCreateView(
 
 -         inflater: LayoutInflater, container: ViewGroup?,
 
 -         savedInstanceState: Bundle?
 
 -     ): View? {
 
 -         val view = inflater.inflate(R.layout.fragment_my, container, false)
 
 -         val textView: TextView = view.findViewById(R.id.textViewNetworkData)
 
  
-         // 观察LiveData
 
 -         myViewModel.networkData.observe(viewLifecycleOwner, Observer { newData ->
 
 -             textView.text = newData
 
 -         })
 
  
-         // 加载数据
 
 -         myViewModel.loadDataFromNetwork("https://example.com/data")
 
  
-         return view
 
 -     }
 
 - }
 
 
  复制代码 在这个例子中,网络请求是在协程的IO调度器上执行的,因此不会阻塞主线程,从而避免了NetworkOnMainThreadException。当数据加载完成时,ViewModel通过LiveData将结果发布给UI层,UI层观察这个LiveData并在数据变化时更新界面。 
 
 |   
 
 
 
 |