当前课程知识点:Android应用开发基础 > 第六章 Android服务 > 6.4 多线程 > 6.4 多线程
本节我们介绍如何使多线程
应用程序启动后
系统会创建一个主线程 main thread
这个主线程负责向UI组件分发事件
主线程的应用
和Android的UI组件发生交互
所以主线程也称为UI线程
在UI线程中
如果做一些比较耗时的工作
比如访问网络或者数据库查询
都会阻塞UI线程
导致事件停止分发
用户体验感觉程序比较卡
没有反应
因此 主线程有两个原则
1 不要早应用程序中阻塞UI线程
2 不要在UI线程外访问UI组件
下面我们看一个
在UI线程中做一些比较耗时的工作
比如访问网络的实例
如图所示
比如常见的QQ登录程序
输入用户名和密码登录后
程序要访问服务器网络
由于需要从服务器下载好友列表
和一些消息
有时候网络速度也许不流畅
服务器的访问可能会比较耗时
如果在主线程中访问网络
会阻塞UI线程
程序会比较卡
用户体验就不好
怎么解决应用中的耗时问题呢
如图所示
android提供了多线程的模式
用新的线程myRun访问网络
但是它违反了主线程第二条原则
从非UI线程访问UI组件
会导致未定义和不能预料的行为
为了解决这个问题
Android提供了一些方法
实现其他线程访问UI线程
第一种方法是使用Handler机制
子线程获取子线程的Handler
将数据放入UI线程的消息队列
UI线程从消息队列中
获取消息后更新UI组件
这种方式的不足之处是代码冗余
子线程和UI线程需要耦合
第二种方法直接使用runOnUiThread机制
将子线程的内容放入runOnUiThread中
子线程在UI线程空闲的时候运行
这种机制的好处是代码简练
耦合度低
上一节我们学习了Service服务
那么服务是多线程吗
我们在服务的函数中使用Log标签
可以看到服务所处的线程
如图所示
通过Thread.currentThread().getId()
这个接口
可以看到日志
日志中可以看到
主视图MainActivity
与开启的服务Service的线程号是一致的
Service虽然在后台运行
但是服务与视图本质上处于同一个线程
如图所示
视图 服务以及服务启动的下载功能
本质上都还在同一个线程
如果在启动服务中
增加了一些耗时操作
如图所示
在服务的onStartCommand中
使用Thread.sleep(5000)阻塞线程5秒
结果如图所示
由于开始服务后
服务与主线程是同一个线程
服务最终会耗时5秒
UI主线程也阻塞了5秒
此时UI控件毫无反应
程序卡住了
因此
服务中不能完成耗时的操作
Android为了解决服务中
不能完成耗时的操作
引入了IntentService
支持异步任务的处理
如图所示
IntentService是继承并处理
异步请求的一个类
在IntentService内有一个工作线程
onHandleIntent来处理耗时操作
启动IntentService的方式
和启动传统的Service一样
同时
当任务执行完后
IntentService会自动停止
而不需要我们手动
或者去控制或stopSelf()去完成
另外
可以启动IntentService多次
而每一个耗时的操作
会以工作队列的方式
在IntentService的onHandleIntent
回调方法中执行
我们新建一个MyIntentService
继承于IntentService类
如图所示
在onHandleIntent方法中
使用Thread.sleep(5000)阻塞线程5秒
在主视图Activitiy中
启动MyIntentService
使用Thread.currentThread().getId()
获取主视图和服务的线程号
使用startService启动MyIntentService
Activitiy启动MyIntentService的效果
如图所示
在服务启动后
Activity与服务不在一个线程
onHandleIntent中
Thread.sleep(5000)耗时操作
并没有阻塞主线程
程序没有出现卡的现象
服务完成后自动注销
现在我们介绍AsyncTask
AsyncTask是一种轻量级的异步任务类
它可以在线程池中执行后台任务
然后把执行的进度和最终的结果
传递给主线程
并在主线程中更新UI
从实现上来说
AsyncTask封装了Thread和Handler
通过AsyncTask
可以更加方便的执行后台任务
以及在主线程中访问UI
但是不适合执行特别耗时的后台任务
对于特别耗时的任务来说
需要使用线程池
AsyncTask是一个抽象的泛型类
它提供了Params Progerss
和Result这三个泛型参数
其中Params表示参数的类型
Progress
表示后台任务执行进度的类型
而Result
则表示后台任务的返回结果的类型
如果不需要传递具体的参数
这三个泛型参数可以使用Void来代替
AsyncTask提供了4个核心方法
如图所示
onPreExecute ()
后台任务开始执行时调用
用于进行一些界面上的初始化操作
doInBackground
在子线程中运行
处理所有的耗时任务
onProgressUpdate
如果onPreExecute中调用了
publishProgress方法后
onPreExecute就会被调用
参数由后台任务中传递
可以对UI进行操作
利用参数中的数值
可以对界面元素进行相应的更新
onPostExecute
后台任务执行完后
通过return语句返回时被调用
返回的数据会作为参数传递到此方法中
可以利用返回的数据来进行UI操作
比如说提醒任务执行的结果
以及关闭掉进度条对话框等
下面我看一下AsyncTask的具体实现过程
我们新建一个MyAsyncTask
继承AsyncTask类
如图所示
AsyncTask的三个参数分别为
1 实现AsyncTask的onPreExecute
doInBackground
onPostExecute
onProgressUpdate的方法
并加上log标签
2 doInBackground中的参数strings
为启动MyAsyncTask的时候传入了参数
使用publishProgress后
会执行onProcessUpdate方法
3 onPostExecute参数args3
为doInBackground返回值
4 onProgressUpdate参数args2
为publishProgress返回值
AsyncTask启动方法如图所示
新建AsyncTask任务对象
使用AsyncTask的execute方法启动任务
并传入参数AsyncTask test1
我们最后看一下实现的AsyncTask效果
如图所示
MainActivity中启动AsyncTask
后台任务开始执行时
调用onPreExecute
在子线程中运行doInBackground
子线程中运行完publishProgress函数后
onProgressUpdate被调用
子线程结束后调用onPostExecute
这就是服务中使用多线程的例子
-Android Studio4.1.2安装常用问题汇总2021.3.15
-1.1 Android概述
--1.1 Android Studio安装与配置-实践案例
-1.1 Android概述--作业
-1.2 Android程序
-1.2 Android程序--作业
-1.3 Android程序调试
-1.3 Android程序调试--作业
-2.1 Activity概述
-2.1 Activity概述--作业
-2.2 Activity应用
-第2章 Android视图--2.2 Activity应用
-3.1 Activity布局
-3.1 Activity布局--作业
-3.2 Android基础组件
-3.2 Android基础组件--作业
-3.3 Android中级组件
-3.3 Android中级组件--作业
-3.4 Android适配器
-3.4 Android适配器--作业
-4.1 Fragment碎片组件
-4.1 Fragment碎片组件--作业
-4.2 ViewPager翻页类组件
-4.2 ViewPager翻页类组件--作业
-讨论:fragment与activity的生命周期有哪些不同?
-5.1 Android广播概述
-5.1 Android广播概述--作业
-5.2 Android广播工作原理
-5.2 Android广播工作原理--作业
-5.3 自定义广播
-第5章 广播--5.3 自定义广播
-5.4 有序广播
--5.4有序广播
-第5章 广播--5.4 有序广播
-6.1 系统服务概述
-6.1 系统服务概述--作业
-6.2 访问系统服务
-6.2 访问系统服务--作业
-6.3 自定义服务
-第6章 Android服务--6.3 自定义服务
-6.4 多线程
--6.4 多线程
-第6章 Android服务--6.4 多线程
-7.1 Android运行权限
-7.1 Android运行权限--作业
-7.2 URL URI概述
-第7章 内容提供者ContentProvider--7.2 URL URI概述
-7.3 ContentProvider概述
-第7章 内容提供者ContentProvider--7.3 ContentProvider概述
-7.4 访问通讯录
-第7章 内容提供者ContentProvider--7.4 访问通讯录
-7.5 课后作业案例
-8.1 相机服务
--8.1 相机服务
-8.1 相机服务--作业
-8.2 音视频服务
-8.2 音视频服务--作业
-9.1 网络服务概述
-9.1 网络服务概述--作业
-9.2 网络框架
--9.2 网络框架
-9.2 网络框架--作业
-9.3 Json
--9.3 Json
-第9章 网络技术--9.3 Json
-9.4 Volley
-第9章 网络技术--9.4 Volley
-10.1 文件存储
--10.1.3 实践案例-SharedPreference文件读写
-10.1 文件存储--作业
-10.2 数据库存储
-10.2 数据库存储--作业
-第1章 实训简介以及开发环境配置
-第2章 在线音乐播放器整体设计以及服务端开发
-第3章 在线音乐播放器-客户端开发
-第4章 在线音乐播放器-完整版
-第5章 QQ聊天项目
-第6章 在线点餐系统