目录
Handler介绍:
1,什么是handler:
2,为什么使用handler
3,handler有什么用:
4, 怎么使用handler
Handler常用方法
1,Handler构造方法:
2,Handler公共方法:
公共方法
Handler 源码理解
1,Handler四大核心对象:
2,原理图:
3,Message类介绍:
4,Handler()构造 (取出looper对象)
5,ActivityThread(存Looper对象)
6,Handler发送消息
7,Handler内部进行取消息 ,并且进行处理
handler使用:
post(Runnable r)在子线程更新UI时使用
sendEmptyMessage发送空标记消息
sendMessage发送标记消息
postDelayed延时更新UI
总结:
10-06 02:17:57.778: W/System.err(1596): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
post(Runnable)
|
post(Runnable)
|
sendMessage(Message)
|
sendMessageAtTime(Message, long)
|
postAtTime(java.lang.Runnable, long)
|
postDelayed(Runnable, Object, long)
|
sendEmptyMessage(int)
|
sendMessageDelayed(Message, long)
|
Handler()
|
默认构造函数将此处理程序与Looper用于当前线程。 |
Handler(Handler.Callback callback)
|
构造函数将此处理程序与Looper对于当前线程,并接受一个回调接口,您可以在其中处理消息。 |
Handler(Looper looper)
|
使用所提供的Looper而不是默认的。 |
Handler(Looper looper, Handler.Callback callback)
|
使用所提供的Looper而不是默认的,而是接受一个回调接口来处理消息。 |
公共方法 |
|
|
static Handler |
createAsync(Looper looper, Handler.Callback callback)
|
创建一个新的Handler,其发布的消息和运行程序不受同步障碍(如显示vsync)的限制。 |
static Handler |
createAsync(Looper looper)
|
创建一个新的Handler,其发布的消息和运行程序不受同步障碍(如显示vsync)的限制。 |
void |
dispatchMessage(Message msg) |
在这里处理系统消息。 |
final void |
dump(Printer pw, String prefix) |
|
final Looper |
getLooper() |
|
String |
getMessageName(Message message)
|
返回表示指定消息的名称的字符串。 |
void |
handleMessage(Message msg)
|
子类必须实现这一点才能接收消息。 |
final boolean |
hasCallbacks(Runnable r)
|
检查消息队列中是否有带有回调r的挂起的消息。 |
final boolean |
hasMessages(int what)
|
检查消息队列中是否有代码“什么”的挂起的消息。 |
final boolean |
hasMessages(int what, Object object)
|
检查消息队列中是否有代码“什么”和其obj是“Object”的挂起的消息。 |
final Message |
obtainMessage(int what, Object obj)
|
同obtainMessage(),只是它还设置了返回消息的内容和obj成员。 |
final Message |
obtainMessage()
|
返回一个新的Message来自全局消息池。 |
final Message |
obtainMessage(int what, int arg1, int arg2)
|
同obtainMessage(),只是它还设置了返回消息的内容、arg 1和arg 2成员。 |
final Message |
obtainMessage(int what, int arg1, int arg2, Object obj)
|
同obtainMessage(),只是它还在返回的消息上设置了什么值、obj值、arg 1值和arg 2值。 |
final Message |
obtainMessage(int what)
|
同obtainMessage(),除非它还设置返回消息的哪个成员。 |
final boolean |
post(Runnable r)
|
导致将Runnable r添加到消息队列中。 |
final boolean |
postAtFrontOfQueue(Runnable r)
|
向实现Runnable的对象发布消息。 |
final boolean |
postAtTime(Runnable r, long uptimeMillis)
|
使Runnable r添加到消息队列,并在uptimeMillis. |
final boolean |
postAtTime(Runnable r, Object token, long uptimeMillis)
|
使Runnable r添加到消息队列,并在uptimeMillis. |
final boolean |
postDelayed(Runnable r, long delayMillis)
|
使Runnable r被添加到消息队列,并在指定的时间流逝后运行。 |
final boolean |
postDelayed(Runnable r, Object token, long delayMillis)
|
使Runnable r被添加到消息队列,并在指定的时间流逝后运行。 |
final void |
removeCallbacks(Runnable r)
|
删除消息队列中所有可运行r的挂起的帖子。 |
final void |
removeCallbacks(Runnable r, Object token)
|
删除所有可运行的挂起的帖子r有对象令牌在消息队列中。 |
final void |
removeCallbacksAndMessages(Object token)
|
删除所有挂起的回调文章,并发送以下消息OBJ是令牌. |
final void |
removeMessages(int what)
|
删除消息队列中任何带有代码“什么”的挂起的消息。 |
final void |
removeMessages(int what, Object object)
|
删除任何挂起的消息,其代码为“什么”,其obj是消息队列中的“对象”。 |
final boolean |
sendEmptyMessage(int what)
|
发送只包含哪些值的消息。 |
final boolean |
sendEmptyMessageAtTime(int what, long uptimeMillis)
|
发送只包含要在特定时间传递的值的消息。 |
final boolean |
sendEmptyMessageDelayed(int what, long delayMillis)
|
发送一条消息,该消息只包含要在指定的时间间隔后传递的值。 |
final boolean |
sendMessage(Message msg)
|
将消息推送到消息队列的末尾,在当前时间之前完成所有挂起的消息。 |
final boolean |
sendMessageAtFrontOfQueue(Message msg)
|
将消息队列放在消息队列的前面,在消息循环的下一次迭代中进行处理。 |
boolean |
sendMessageAtTime(Message msg, long uptimeMillis) |
在所有挂起的消息在绝对时间之前(以毫秒为单位)之前,将消息放入消息队列中。uptimeMillis. |
final boolean |
sendMessageDelayed(Message msg, long delayMillis)
|
在所有挂起的消息之前(当前时间+delayMillis)之后,将消息放入消息队列中。 |
String |
toString() |
返回对象的字符串表示形式。 |
【1】核心类
Message: 消息(数据载体).
Looper: 轮询器. 去MessageQueue取消息 分发给Handler处理
MessageQueue: 消息队列(存储消息).
Handler: 消息处理器. 发送消息 处理消息
【2】对应关系
handler和Looper的关系是多对一的,在主线程new Handler多个但是 都是通过ActivityThread 主线程中获取的一个Looper对象进行处理*
looper和MessageQueue消息队列的关系是一一对应的关系
【1】什么是Message?
Message是封装了需要传递的数据交由Handler 处理的对象。
在android的消息机制中,Message其充当着信息载体的一个角色,通俗的来说,我们看作消息机制就是个工厂的流水线,message就是流水线上的产品,messageQueue就是流水线的传送带。
Android的消息机制都通过message这个载体进行传递消息。
【2】Message的作用:
用于存放传递的数据;
是主线程和子线程传递数据的载体
Message message= new Message();
Message message= Message.obtain();
Messager message= handler.obtaionMessager();
向Message中添加数据:
Message message = Message.obtain();
//TODO 将传递数据,封装到Message消息对象中
message.what = 0;
message.arg1 = 1;
message.arg2 = 2;
message.obj = “传递的内容”;
Bundle bundle = new Bundle();
bundle.putString("name","张三");
message.setData(bundle);
获取Message中存储的数据
private Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int flag1 = msg.what;
int flag2 = msg.arg1;
int flag3 = msg.arg2;
String resultMsg = (String) msg.obj;
Bundle bundle = msg.getData();
String name = bundle.getString("name");
}
};
Handler.obtain() 底层调用的是Message.obtain()
Message.obtain() 从池子取对象,单向链表 next复用Message,如果没有会new Message()
new Message()
【5】Message.obtain() 可以复用消息 , 单向链表
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
hanlder()构造方法,取出looper对象
public Handler(Callback callback, boolean async) {
//这里是异常判断
if (FIND_POTENTIAL_LEAKS) {
final Class extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//给looper变量赋值
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler() {
// 给looper变量赋值
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// 当looper被调用后,获取mLooper对象给mQueue消息队列赋值,
mQueue = mLooper.mQueue;
mCallback = null;
}
public static final Looper myLooper() {
// 从当前线程取Looper对象,你在子线程中开启handler会报错,因为子线程中,没有把线程存放进去
return (Looper)sThreadLocal.get(); //多线程中确认线程唯一的对象, sThreadLocal.get() 就是从线程池中取一个唯一对象
}
public static final void main(String[] args) {
// 往主线程设置Looper对象
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
//主线程进入死循环
Looper.loop();
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
if (Process.supportsProcesses()) {
myLooper().mQueue.mQuitAllowed = false;
}
}
public static final void prepare( ) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 往当前线程设置Looper对象
sThreadLocal.set(new Looper());
}
private Looper() {
// 创建消息队列
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
handler.sendMessage()
sendMessageDelayed(Message msg, long delayMillis)
sendEmptyMessageAtTime(int what, long uptimeMillis)
sendEmptyMessageDelayed(int what, long delayMillis)
sendEmptyMessage(int what)
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
// 把消息传递给消息队列
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
final boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
// 当前发送的消息需要马上处理,排到队列头
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
/ 当前发送的消息不需要马上处理,根据时间重新排序
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
}
// 根据是否需要唤醒,处理消息
if (needWake) {
nativeWake(mPtr);
}
return true;
}
public static final void main(String[] args) {
// 往主线程设置Looper对象
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
//主线程进入死循环
Looper.loop();
}
public static final void loop() {
Looper me = myLooper();
// 主线程进入死循环
while (true) {
}
}
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
while (true) {
// 从消息队列取消息,如果没有消息就阻塞
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
// 处理消息 target指发送此消息的handler
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf("Looper", "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public class TestActivity extends AppCompatActivity {
private Handler mHandler = new Handler();
private ImageView mImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mImageView = (ImageView) findViewById(R.id.image);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
mHandler.post(new Runnable() {
@Override
public void run() {
mImageView.setImageResource(R.mipmap.ic_launcher);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
public class TestActivity extends AppCompatActivity {
private ImageView mImageView;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg.what == 0x123) {
mImageView.setImageResource(R.mipmap.ic_launcher);
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mImageView = (ImageView) findViewById(R.id.image);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
mHandler.sendEmptyMessage(0x123);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
1, handler.sendMessage(msg);
创建Handler对象,重写handleMessage 方法
开启子线程,通过Message.obtaion方法获取到Message对象
给Message对象添加内容,和标记, handler.sendMessage(msg);在子线程发送消息
在handler对象中的HandleMessage方法里,获取到对应的what进行处理消息
2,实现原理:
【1】开启子线程处理耗时操作,使用handler传输数据:
// 实现按钮点击事件
public void click(View v) {
//创建一个子线程
new Thread() {
public void run() {
try {
if(xxxx){
// 把耗时的操作放到子线程里面 bitmap 是要传输的数据
Bitmap bitmap = BitmapFactory.decodeStream(in);
// 获取message对象,不去 new Message() 使用obtain方法是为了避免创建过多的对象
Message msg = Message.obtain();
// 数据塞进msg里面
msg.obj = bitmap;
// 给msg 加一个标识在handler 可以分类进行逻辑处理
msg.what = REQUESTSUCESS;
handler.sendMessage(msg);
}else {
Message msg = Message.obtain();
msg.what = REQUESTFAIL;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
Message msg = Message.obtain();
msg.what = REQUESTEXCEPTION;
handler.sendMessage(msg);
}
}
}.start();
【2】创建handler成员变量,接收数据进行UI操作:
protected static final int REQUESTSUCESS = 0;
protected static final int REQUESTFAIL = 1;
protected static final int REQUESTEXCEPTION= 2;
//定义一个handler
private Handler handler = new Handler(){
//在这个方法里面处理消息
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case REQUESTSUCESS:
//[1]获取我们携带的数据
Bitmap bitmap = (Bitmap) msg.obj;
//[2]把btimap展示到imagview上
iv.setImageBitmap(bitmap);
break;
case REQUESTFAIL:
iv.setImageBitmap(null);
Toast.makeText(getApplicationContext(), "图片不存在", 1).show();
break;
case REQUESTEXCEPTION:
iv.setImageBitmap(null);
Toast.makeText(getApplicationContext(), "图服务器忙", 1).show();
break;
}
};
};
1,handler.postDelayed(Runnable r, int i)
发送一个消息,在int i 设置多少之后进行执行
2,实现效果
【1】hanlder设置一个延时任务:
参1 任务 参2延时时间
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
需要实现的逻辑
}
}, 2000);
handler 是android 中处理消息,用于更新UI,我们可以用来实现广告条的轮播,延时任务执行,更新UI,处理数据,和发送数据的使用。
全篇分析介绍了handler,分析handler的源码,还有handler常规的使用方法,希望可以帮助到各位。请点赞支持,相互交流。回谢