两种实现方式:
- extends Thread类,复写run();
- 实现Runnable接口,复写run()方法,获得的对象传入Thread类构建新线程的构造方法中。
安卓线程分类
- MainThread:UI线程运行UI相关的代码。
- WorkerThread:其他的代码由WokerThread负责。
- 原则上UI相关的修改不允许在WorkerThread上进行修改,但是有些例外的比如修改progressBar的progress()方法。
ANR问题:application not responding
在一个应用程序中主线程通常用于接受用户的输入,并将运算的结果反馈出来
所以主线程不能阻塞,对于一些可能产生阻塞的操作必须放置在WorkerThread中。
如何将workerThread中的问题反馈到MainThread中
Handler(管理者)
Handler运行原理:队列中存放数据对象,具有先进先出的顺序,队列中存放着大量数据,每个都是一个对象,Handler负责将对象加入到消息队列中
1. 使用obtainMessage()方法获得消息对象,使用msg.what复制消息对象。
2. 使用sendMessage方法发送消息到队列中。
Looper(循环器):从消息队列头部不断中取出对象,消息队列中无消息对象时会等待。取出的对象交给Handler处理。
1. 构建一个内部类继承Handler,并且重写其中的handleMessage方法。
2. 这个内部类的Handler对象承担了发送和处理消息的作用,使用int what = msg.what;将Looper接受到的对象取出如何重写handleMessage方法看自己意图。
看我没写调用对象的handleMessage方法,说明是自动 调用的
package com.example.handler01;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.FileReader;
import java.security.PrivateKey;
public class MainActivity extends AppCompatActivity {
Button button;
private FirstHandler firstHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
firstHandler = new FirstHandler();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 当用户点击按钮时,生成一个message对象将其发送出去
//obtainMessage()方法生成一个message对象
Message msg = firstHandler.obtainMessage();
//为message初始化
msg.what = 2;
//发送message
firstHandler.sendMessage(msg);
//lLooper将消息对象取出,找到与消息对象对应的Handler对象,此处为firstHandler,然后调用Handler对象的handleMessage
//方法处理消息对象。
}
});
}
class FirstHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int what = msg.what;
Log.d("msg", what + "");
}
}
}
Handler实现线程之间的通信
- 从WorkerTread()中发送消息到MainThread()
package com.example.handler02;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button button;
private TextView textView;
private MyHandler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text_view);
button = (Button) findViewById(R.id.button);
handler = new MyHandler();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
InternetThread t = new InternetThread();
t.start();
}
});
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
//获取当前线程的名字,在主线程中通过handleMessage处理数据
Log.d("msg","===currentThread is===" +Thread.currentThread().getName() );
String s =(String) msg.obj;
textView.setText(s);
}
}
class InternetThread extends Thread {
@Override
public void run() {
Log.d("msg","===currentThread is===" +Thread.currentThread().getName() );
try {
//模拟访问网络,休眠2秒钟
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模拟网络中的数据
String s = "网络数据";
//在工作线程中获取数据并发送
Message msg = handler.obtainMessage();
//obj用于发送对象
msg.obj = s;
handler.sendMessage(msg);
}
}
}
- 从主线程中向workerThread发送消息
- 在WokerThread准备Looper对象,调用prepare()方法
- 在WokerThread当中生成Handler对象,然后调用Loop()方法
- 在MainThread中发送消息
由此看出主线程直接执行prepare和loop()方法
package com.example.handler03;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.send_msg);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = handler.obtainMessage();
msg.what = 2;
handler.sendMessage(msg);
Log.d("msg", Thread.currentThread().getName() + "--发送了消息对象");
}
});
WokerThread t = new WokerThread();
t.start();
}
class WokerThread extends Thread {
@Override
public void run() {
//准备Looper对象
Looper.prepare();
//生成一个handler对象
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.d("msg", Thread.currentThread().getName() + "收到了message对象");
}
};
//调用Looper类的Loop()方法后,Looper对象会不断的从消息队列中
//取出消息对象,然后调用WokerThread线程中的handleMessage()方法处理对象,如果没有对象传入则该线程阻塞
Looper.loop();
}
}
}
首次安卓源代码之旅
ThreadLocal类和基本思路
- 执行ThreadLocal对象的set(Object obj)方法将会备份一个当前线程对象,然后存储为和变量值相对应的键值对。
- 执行get()方法返回一个和当前线程对象对应的的变量的值。
思路:Looper.prepare()生成一个looper对象和对应的消息队列对象,调用TreadLocal的set()方法将线程对象和looper对象存储成一个本地线程的键值对。
new Handler对象是将looper对象取出赋值给Handler类的mlooper成员变量,建立起了关系。
loop()方法
looper()方法中首先调用myLooper()方法(其中通过sThreadLocal.get()方法获取了当前线程对应 的Looper对象)如果为空的说明没有调用prepare()方法,然后生成了一个消息队列,在一个for(;;)循环中生成一个消息对象,调用了一个消息队列的next()方法,可能返回null or message instance,so if msg == null, the loop() will end ,the message queue will quit ,and then ,msg.target.dispatchMessage(msg); target is an obj of Handler,and the dispatchMessage() method just call the handleMessage() method to handle the message. we use handler.obtainMessage to get a message , when we use handler = new Handler(),we call the mLooper = Looper.myLooper 获得了当前线程的looper对象与Handler建立起连接,一个Looper和一个messagequeue在prepare方法中相对应,使用handler生成message对象的target属性就是handler的值
handler的post方法
直接调用Runnable的run方法
package com.example.handler04;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button button;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyThread m = new MyThread();
m.start();
}
});
}
class MyThread extends Thread {
@Override
public void run() {
handler.post(new Runnable() {
/*public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}*/
// getPostMessage:1.获得一个message对象,2将r对象赋值给callback属性
//返回一个message对象
//sendMessageDelayed()将消息延时发送
//主线程在接受到r对象后,调用了loop()方法,相当于调用了dispatchMessage()方法,因为此时callBack不为空
//所以调用了handleCallback方法直接调用了Runnable的run()方法。
@Override
public void run() {
Log.d("thread", "current thread name is-- " + Thread.currentThread().getName());
}
});
}
}
}