Android里面开子线程的方法

1. Kotlin协程(官方推荐,最现代化)

适用场景 :几乎全部异步任务(网络请求、数据库、耗时计算等)
优点 :轻量级、自动线程切换、避免回调地狱、完美支持生命周期
示例

kotlin

复制代码
// 在Activity/Fragment中(需引入lifecycle-ktx)
lifecycleScope.launch {
    // 默认在主线程执行
    val result = withContext(Dispatchers.IO) { // 切换到IO线程
        // 子线程执行耗时操作(如网络请求)
        fetchDataFromNetwork()
    }
    textView.text = result // 自动切回主线程更新UI
}

关键点

  • Dispatchers.IO:适合磁盘/网络IO操作

  • Dispatchers.Default:适合CPU密集型计算

  • lifecycleScope:自动绑定生命周期,避免内存泄漏


2. Thread + Handler(传统基础方案)

适用场景 :简单后台任务,需要兼容老代码
示例

java

复制代码
// 开启子线程
new Thread(() -> {
    // 在子线程执行耗时任务
    String result = doHeavyWork();
    
    // 通过Handler切回主线程更新UI
    new Handler(Looper.getMainLooper()).post(() -> {
        textView.setText(result);
    });
}).start();

缺点:需手动管理线程,复杂场景易出错


3. ExecutorService(线程池)

适用场景 :需要控制并发数量的任务(如下载多个文件)
示例

java

复制代码
// 创建固定大小的线程池(4个线程)
ExecutorService executor = Executors.newFixedThreadPool(4); 

// 提交任务
executor.execute(() -> {
    // 子线程执行任务
    String data = fetchData();
    
    runOnUiThread(() -> { // 切回主线程
        textView.setText(data);
    });
});

// 关闭线程池(通常在onDestroy中)
executor.shutdown();

优点:复用线程资源,避免频繁创建/销毁开销


4. RxJava(响应式编程)

适用场景 :复杂异步任务链(需额外引入库)
示例

java

复制代码
Observable.fromCallable(() -> {
    // 子线程执行
    return fetchData();
})
.subscribeOn(Schedulers.io()) // 指定子线程执行
.observeOn(AndroidSchedulers.mainThread()) // 切回主线程
.subscribe(data -> {
    textView.setText(data); // 主线程更新UI
});

5. AsyncTask(已废弃,仅了解)

java

复制代码
// ❌ 已废弃!仅用于理解旧代码
private class MyTask extends AsyncTask<Void, Void, String> {
    @Override
    protected String doInBackground(Void... voids) {
        return fetchData(); // 子线程执行
    }

    @Override
    protected void onPostExecute(String result) {
        textView.setText(result); // 主线程更新UI
    }
}
// 启动方式
new MyTask().execute();

关键注意事项

  1. UI线程规则

    • 只有主线程能更新UI,子线程必须通过以下方式切回:

      kotlin

      复制代码
      // Kotlin
      withContext(Dispatchers.Main) { /* 更新UI */ }
      // Java
      runOnUiThread(() -> { /* 更新UI */ });
  2. 内存泄漏

    • 在Activity/Fragment中使用协程时,务必用lifecycleScopeviewModelScope

    • 避免匿名内部类持有外部引用(如非静态Handler)

  3. 线程选择

    场景 推荐调度器
    网络请求/文件读写 Dispatchers.IO
    CPU密集型计算 Dispatchers.Default
    数据库(Room) 无需指定,Room自动优化

终极选择建议

  • 新项目 :无脑选 Kotlin协程viewModelScope/lifecycleScope

  • 老项目

    • 简单任务:Thread + Handler

    • 复杂并发:ExecutorService

    • 已有RxJava:继续使用

    • 协程示例

      复制代码
      // 在ViewModel中
      class MyViewModel : ViewModel() {
          private val _data = MutableLiveData<String>()
          val data: LiveData<String> = _data
      
          fun loadData() {
              viewModelScope.launch {
                  _data.value = "Loading..."
                  try {
                      val result = withContext(Dispatchers.IO) {
                          // 模拟网络请求
                          delay(2000)
                          "加载完成"
                      }
                      _data.value = result
                  } catch (e: Exception) {
                      _data.value = "Error: ${e.message}"
                  }
              }
          }
      }
相关推荐
祖国的好青年37 分钟前
VS Code 搭建 React Native 开发环境(Windows 实战指南)
android·windows·react native·react.js
黄林晴1 小时前
警惕!AGP 9.2 别只改版本号,R8 规则与构建链路全线收紧
android·gradle
小米渣的逆袭1 小时前
Android ADB 完全使用指南
android·adb
儿歌八万首1 小时前
Jetpack Compose Canvas 进阶:结合 animateFloatAsState 让自定义图形动起来
android·动画·compose
zhangphil2 小时前
Android Page 3 Flow读sql数据库媒体文件,Kotlin
android·kotlin
神探小白牙3 小时前
echarts,3d堆叠图
android·3d·echarts
李白的天不白3 小时前
如何项目发布到github上
android·vue.js
summerkissyou19873 小时前
Android-RTC、NTP 和 System Time(系统时间)
android
小书房3 小时前
Kotlin使用体验及理解1
android·开发语言·kotlin
撩得Android一次心动4 小时前
Android Navigation 组件全面讲解
android·jetpack·navigation