Android多线程编程
文章目录
- Android多线程编程
- 线程的基本用法
- 在子进程中更新UI
- 解析异步消息处理机制
线程的基本用法
定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法即可
class MyThread : Thread(){
override fun run(){
//编写具体逻辑
}
}
启动线程很简单
MyThread().start()
当然我们也可以选择用Runnable接口
class MyThread : Runnable{
override fun run(){
//编写逻辑
}
}
启动线程稍微有点不一样
val myThread = MyThread()
Thread(myThread).start()
可以看到,首先Thread需要接收一个Runnable参数,接着在调用start()
第三种写法是使用lambda方式
Thread{
//编写具体逻辑
}.start()
这是再java中的写法,再kotlin中会更加简单
thread{
//编写具体逻辑
}
这是Kotlin内置的一个顶层函数,只需要再{}中写具体逻辑就可以,甚至都不需要写start()
在子进程中更新UI
假如我们要实现以下功能:点击按钮后文本内容改变
我们使用子进程的方式实现。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.changeTextBtn.setOnClickListener {
thread {
binding.textView.text = "Nice to meet you "
}
} }
}
这是因为Android是不允许在子进程中进行UI操作的。
修改代码为
class MainActivity : AppCompatActivity() {
val updateNext = 1
val handler = object : Handler(Looper.getMainLooper()){
override fun handleMessage(msg: Message) {
val textView = findViewById<TextView>(R.id.textView)
when(msg.what){
updateNext ->textView.text = "Nice to meet you"
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.changeTextBtn.setOnClickListener {
thread {
val msg = Message()
msg.what = updateNext
handler.sendMessage(msg)
}
} }
}
首先新建updateText变量,用于表示更新TextView的这个动作。
然后新增一个handler对象,且重写父类handleMessage方法,后根据msg的what内容判断,当接收到updateText时,更新UI。
再来看看changeTextBtn点击事件内容,首先是创建了一个Message对象,后将msg,what设置为updataText,然后调用sendMessage方法发送出去。
这个就是异步消息处理,以下是它的内容讲解
解析异步消息处理机制
异步消息处理主要由四个部分组成
- Message :在线程之间传递少量信息
- Handler : 用于发送和处理
- MessageQueue : 消息队列,用于存放Handler发送的信息
- Looper : 管家,调用Looper的loop方法后,会进入一个无限循环中,每当发现信息队列中有信息,就会将他取出,并且传递到Handler的handleMessage中。
了解一下主要流程
首先在主线程中创建一个Handler对象,并且重写handleMessage()方法,然后当子线程需要改变UI时,新建一个Message对象,通过handle发送出去。这样这条信息就被添加到MessageQueue中等待被处理。而且Looper会一直尝试从MessageQueue中取出信息,最后分发到Handler的handlerMessage中。(Handle的构造对象中传入了Looper.getMainLooper)