一.Java推荐的基础三种线程方式
1.【继承法,耦合度高】定义一个线程:新建一个类继承自Thread,重写父类run方法即可
2. 新建实例对象,通过start()即可执行线程的run操作
2. 【实现接口法】:实现Runnable接口,调用时通过new这个实现的接口对象,再将其传入Thread构造方法再start即可
3. 匿名类方式
补充:
1. Kotlin实现Runnable
- 创建Thread对象来创建线程
// 创建Thread
val mThread = CustomThread()
// 调用
mThread.start()
// ============================================
// 继承Thread
class CustomThread : Thread() {
// 重写run()方法
override fun run() {
super.run()
Thread.sleep(1000)
println("延迟1s打印")
}
}
- 通过实现Runnable接口来创建线程
val mRunnable = Runnable1 {//导dava的包显示多一个1
run {
Thread.sleep(5000)
println("5s后打印输出")
println("1111线程测试 常规Runnable为" + Thread.currentThread())
}
}
// ============================================
Thread(mRunnable).start()
-
测试发现,在start()方法内部调用了run()方法,主要目的是创建一个新线程。 如果直接调用run()方法,则不会创建新线程,而是将在同一线程上执行run()。 这意味着你应该始终通过调用Java中的Thread.start()方法来启动线程。(样例中常规的是指start方式)
-
Kotlin直接就打开就行了
二.线程与更新UI
1. 异步消息处理机制介绍:
- Message(传递的消息)
- Handler(处理者,发送和处理消息)
- MessageQueue(消息队列存放消息)
- Looper(执行线程中的message循环,调用Looper的loop()方法后就会进入无限循环,每发现Queue中存在一条消息,就会将其取出)
2. 采用Handler从子线程发送handleMessage回主线程,使用匿名内部类
- Android Handler:这是一份 全面、详细的Handler机制 学习攻略
- 子线程与主线程通信,evnetbus等都是通过handler
- 你真的懂Handler吗
- Handler本就是通过message事件驱动的,无事件主线程就sleep休眠了,用户交互上当然感觉不到异常,这和anr是不同的概念。
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
// 在这里可以进行UI操作
text.setText("Nice to meet you");
break;
default:
break;
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message); // 将Message对象发送出去
}
}).start();
3. 子线程中新建Handler方式【不然会报错】
三.使用AsyncTask【抽象类需继承】
//启动任务:
new DownloadTask().execute()
//新建类继承AsyncTask:
class DownloadTask extends AsyncTask<Void, Integer, Boolean> {//不需要传参给后台任务,进度显示单位为int,使用boolean来反馈执行结果
protected void onPreExecute() {
progressDialog.show(); // 显示进度对话框
}
@Override
protected Boolean doInBackground(Void... params) {
try {
while (true) {
int downloadPercent = doDownload(); // 这是一个虚构的方法
publishProgress(downloadPercent);
if (downloadPercent >= 100) {
break;
}
}
} catch (Exception e) {
return false;
}
return true;
}
@Override
protected void onProgressUpdate(Integer... values) {
// 在这里更新下载进度
progressDialog.setMessage("Downloaded " + values[0] + "%");
}
@Override
protected void onPostExecute(Boolean result) {
progressDialog.dismiss(); // 关闭进度对话框
// 在这里提示下载结果
if (result) {
Toast.makeText(context, "Download succeeded",Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(context, " Download failed", Toast.LENGTH_SHORT).show();
}
}
}
四.通过postDelayed进行延时消息
1. View控件进行[Post延时,就是在主线程中的]
- 例一
- 例二
Handler().postDelayed(Runnable { rotateAnimation!!.start() }, 2000)
2.handler消息机制与延时
- handler方法其中有send和post两种方法
1)大家常用的send方法,其是在工作线程中处理完耗时操作后调用handler的sendMessage(message)把message对象发送给主线程,在主线程中重写handlerMessage()方法,
2)而post方法传递的是一个runnable对象,更新UI的操作也是在这个runnable的run方法中进行的,也就是说run方法中的代码是执行在主线程中的,虽然它是写在工作线程中,主线程在接收到消息后自动执行runnable的run方法中的代码。)
send和post源码
注解
t
5. 使用runOnUiThread线程判断及切换主线程进行toast的线程处理
6. 测试数据
- AsyncTask【三个参数分别是:线程名称, 线程优先级, 线程所属线程组】
- Thread(和上面的Runnable类似)
- IO协程中