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}"
                  }
              }
          }
      }
相关推荐
练习本2 小时前
Android系统架构模式分析
android·java·架构·系统架构
每次的天空7 小时前
Kotlin 内联函数深度解析:从源码到实践优化
android·开发语言·kotlin
练习本7 小时前
Android MVC架构的现代化改造:构建清晰单向数据流
android·架构·mvc
早上好啊! 树哥8 小时前
android studio开发:设置屏幕朝向为竖屏,强制应用的包体始终以竖屏(纵向)展示
android·ide·android studio
YY_pdd8 小时前
使用go开发安卓程序
android·golang
Android 小码峰啊10 小时前
Android Compose 框架物理动画之捕捉动画深入剖析(29)
android·spring
bubiyoushang88810 小时前
深入探索Laravel框架中的Blade模板引擎
android·android studio·laravel
cyy29810 小时前
android 记录应用内存
android·linux·运维
CYRUS STUDIO11 小时前
adb 实用命令汇总
android·adb·命令模式·工具
这儿有一堆花11 小时前
安卓应用卡顿、性能低下的背后原因
android·安卓