Android中线程按功能分的话,可以分为两个,一个是主线程(UI线程),其他的都是子线程

主线程不能执行那些耗时过长的代码或任务(执行耗时过长的代码会出现应用未响应的提示),所以都是使用子线程来执行耗时过长的代码,比如说下载文件等任务

一般情况,子线程中执行过长的代码,都是需要进行更新UI操作。

但是Android中,为了防止安全,是不允许在子线程更新UI的,但是我们可以使用到Android官方给予的API来实现子线程更新UI的操作(本质上,这些API也是切换回了主线程来进行更新UI)

例子:点击一个按钮,过了1s后完成了下载任务,返回了数据,此数据会显示在界面上

具体解释:

点击按钮,之后开启一个子线程来模拟下载过程(线程休眠1s),之后任务执行完毕会返回数据(一个String),使用返回的数据更新UI

新建一个方法,用来模拟下载任务

/**
* 模拟下载
*/
fun download(): String {
Thread.sleep(1000)
return "this is data"
}

下面的使用6种方式和上面的模拟下载任务的方法,来实现上面例子的效果

1.Activity.runOnUiThread()

runOnUiThread是Activity中的方法,只有当前对象是Activity,就可以直接使用,如果当前的对象不是Activity,需要找到Activity对象,才能执行此方法

runOnUiThread方法的参数为一个Runnable接口,我使用的kotlin,所以有很多东西都是省略了

设置按钮的点击事件,点击按钮开启一个线程

btn_start.setOnClickListener {
thread {
val data = download()
runOnUiThread({
//这里进行更新UI操作
tv_show.text = data
})
}
}

Java版

btn_start.setOnClickListener(new OnClickListener(){
new Thread(new Runnable(){
String data = download();
runOnUiThread(new Runnable(){
@Override
public void run() {
tv_show.setText(data);
}
})
}).start();
});

2.View.post()

post方法是View对象的方法,参数也是接收一个runnable接口

这里我选用的view对象是需要进行更新textview的本身,当然也可以选用其他的View对象,只要是在当前Activity的对象都可以

btn_start.setOnClickListener {
thread {
val data = download()
//选择当前Activity的View对象都可以
tv_show.post {
tv_show.text = data
}
}
}

3.View.PostDelayed()

此方法和上面的post方法类似,只是多一个参数,用来实现延迟更新UI的效果

btn_start.setOnClickListener {
thread {
val data = download()
tv_show.postDelayed({
tv_show.text = data
},2000)
}
}

上面的代码实现的效果是点击按钮之后,过了3s后才会看到界面发生改变

4.Handler.post()

new一个Handler对象(全局变量)

private val handler = Handler()

使用post方法更新UI,此post方法和之前的post方法一样,参数都是为Runnable接口

btn_start.setOnClickListener {
thread {
val data = download()
handler.post {
tv_show.text = data
}
}
}

5.AsyncTask(推荐)

说明

AsyncTask是一个抽象类,必须创建一个子类类继承它

这里介绍一下关于AsyncTask的三个泛型参数和几个方法

泛型参数可以为任意类型,为空的话使用Void

参数 说明
params 参数泛型,doInBackground方法的参数
progress 进度泛型,onProgressUpdate方法的参数
result 结果泛型,onPostExecute方法的参数

抽象方法说明:

方法名 说明
onPreExectute() 此方法中,常常进行初始化操作,如进度条显示
doInBackground(Params...) 此方法必须实现,
onProgressUpdate(Progress...) 进行更新UI的操作
publishProgress(Progress...) 在doInBackground方法中调用,调用此方法后会回调执行onProgressUpdate方法进行更新UI
onPostExcute(Result) 任务结束之后进行更新UI

简单来说,如果子类继承了AsyncTask,它的抽象方法的参数都会变成泛型对应的类型

例子

下面的代码是取自我的APP,简单地说明一下AsyncTask<String, DownloadingItem, DownloadedItem>

我传入的是3个泛型参数分别为StringDownloadingItemDownloadedItem,分别对应的paramsprogressresult泛型

这里我是根据自己的需要而两个类DownloadingItemDownloadedItem,从下面的代码可以看到,抽象方法的参数变为了我们的泛型的类型

internal inner class DownloadingTask : AsyncTask<String, DownloadingItem, DownloadedItem>() {

	override fun onPreExecute() {
//一些初始化操作
} override fun doInBackground(vararg params: String?): DownloadedItem {
//params是一个参数数组,如果创建DownloadingTask对象只传入了一个参数,直接取下标为0的那个即可(需要转型)
//耗时操作(如下载操作),获得进度数据 //将新的进度数据传递到onProgressUpdate方法,更新UI
publishProgress(messageItem) //任务执行完毕,返回结果(回调onPostExecute方法)
} override fun onProgressUpdate(vararg values: DownloadingItem?) {
//这里使用最新的进度来进行相关UI的更新
//values是一个DownloadingItem数组,取末尾那个即为最新的进度数据
} override fun onPostExecute(result: DownloadedItem?) {
//下载成功提示或者是其他更新UI的操作
}
}

执行:

执行Task的时候需要在主线程(UI线程调用)

DownloadingTask().execute("参数")

批量下载:

//允许在同一时刻有5个任务正在执行,并且最多能够存储50个任务
private val exec = ThreadPoolExecutor(5, 50, 10, TimeUnit.SECONDS, LinkedBlockingQueue<Runnable>())
DownloadingTask().executeOnExecutor(exec, url)

6.Handler机制实现(核心)

其实,Handler机制是子进程更新UI的核心

我们上面的五种实现子进程更新UI的方式,都是基于Handler机制实现的

具体机制本文就不多说了,网上有许多的机制说明,这里就只讲一下实现的步骤

Message中有几个属性,whatarg1arg2,这三个都是接收一个Int,所以,传递数据不是很友好,这里就不准备实现之前的例子效果了

what表示来源,arg1和arg2用来传递Int数据

1.重写Handler类中的handleMessage方法

一般都是规定好一个Int的常量,来表示what

private val handler =object : Handler(){
override fun handleMessage(msg: Message?) {
if (msg.what == 1) {
//来源为1,则
}
}
}

2.发送Message

val msg = handler.obtainMessage()
//一般都是规定好一个Int的常量,来表示what
msg.what = 1
//传递Int数据
msg.arg1 = 20
handler.sendMessage(msg)

Android开发——实现子线程更新UI的更多相关文章

  1. [Android学习笔记]子线程更新UI线程方法之Handler

    关于此笔记 不讨论: 1.不讨论Handler实现细节 2.不讨论android线程派发细节 讨论: 子线程如何简单的使用Handler更新UI 问题: android开发时,如何在子线程更新UI? ...

  2. Android子线程更新UI的方法总结

    版权声明:本文为博主原创文章,转载请注明出处:https://i.cnblogs.com/EditPosts.aspx?postid=6121280 消息机制,对于Android开发者来说,应该是非常 ...

  3. Android可以子线程更新UI?

    初了解Android的时候,就知道Android是不能在子线程更新UI的,不然程序会直接抛出异常,告诉你,别给我在自线程搞事情! 但是,这个是针对普通的view做的限制,而TextureView,Su ...

  4. android子线程更新UI

    参考:https://www.cnblogs.com/joy99/p/6121280.html 子线程是不能直接更新UI的.Android实现View更新有两组方法,分别是invalidate和pos ...

  5. Android子线程更新UI成功

    android子线程更新UI成功 今天在写demo的时候,在子线程中更新UI,发现更新成功,记录一下. protected void onCreate(Bundle savedInstanceStat ...

  6. Android通过子线程更新UI的几种方式

    一般情况下,UI的更新都少不了Handler,首先我们先了解一下Handler机制: Handler消息机制 定义 Message 线程间通信的数据单元,可通过message携带需要的数据创建对象:M ...

  7. OkHttp3几个简单的例子和在子线程更新UI线程的方法

    okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...

  8. 子线程更新UI界面的2种方法

    一.一般我们都会在子线程完成一些耗时的操作. 1.Android中消息机制: 2.知识点: Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队, ...

  9. Python+PyQT5的子线程更新UI界面的实例《新手必学》

    今天小编就为大家分享一篇Python+PyQT5的子线程更新UI界面的实例,具有很好的参考价值,希望对大家有所帮助.一起跟随小编过来看看吧子线程里是不能更新UI界面的,在移动端方面.Android的U ...

随机推荐

  1. Oil Deposits UVA - 572

    The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSu ...

  2. Map.Entry 接口

    Map.Entry Map 接口下面的 Entry 接口. 该接口,定义一个键值对实体接口.Map.entrySet 方法返回的 Set 集合中的实体就是实现这个 它.只有一种方法可以获得 Map.E ...

  3. Go语言基础之单元测试

    不写测试的开发不是好程序员.我个人非常崇尚TDD(Test Driven Development)的,然而可惜的是国内的程序员都不太关注测试这一部分. 这篇文章主要介绍下在Go语言中如何做单元测试和基 ...

  4. 快速了解TCP的流量控制与拥塞控制

    有关TCP你不能不知道的三次握手和四次挥手问题,点我跳转 流量控制 1. 滑动窗口 数据的传送过程中很可能出现接收方来不及接收的情况,这时就需要对发送方进行控制以免数据丢失.利用滑动窗口机制可以很方便 ...

  5. 如何部署 H5 游戏到云服务器?

    在自学游戏开发的路上,最有成就感的时刻就是将自己的小游戏做出来分享给朋友试玩,原生的游戏开可以打包分享,小游戏上线流程又长,那 H5 小游戏该怎么分享呢?本文就带大家通过 nginx 将构建好的 H5 ...

  6. Thinkphp5.0 仿百度糯米 开发多商家 电商平台(完整版)

    目录第1章 课程简介第2章 需求分析第3章 快速掌握thinkphp5第4章 任性的TP5模块第5章 生活服务分类管理模块第6章 百度地图应用封装第7章 打造属于TP5自己的发送邮件服务第8章 商户模 ...

  7. Windows下更换MAC地址

    使用TMAC软件是最佳方案.官网地址:www.technitium.com

  8. js vue 页面添加水印

    vue 微信页面添加水印 this.$nextTick(function() {                                   watermark({ watermark_txt ...

  9. JavaScript之基本概念(一)

    在我们学习一门编程语言之前,我们应该先了解它的一些基本概念,包括它是什么,它能用来干什么,怎么用等等.这部分内容建议学习时间一天. 一 何为‘JavaScript’ 1 .    什么是JavaScr ...

  10. Android 正 N 边形圆角头像的实现

    卖一下广告,欢迎大家关注我的微信公众号,扫一扫下方二维码或搜索微信号 stormjun94(徐公码字),即可关注. 目前专注于 Android 开发,主要分享 Android开发相关知识和一些相关的优 ...