Handler是啥子,简而言之就是一个用来更新UI的一套机制,和消息处理的机制;
在看代码前,来捋一捋思路。
一般而言,我们常用的Handler的方法主要就有,post,postDelayed,sendMessage,sendMessageDelayed;
现在在来看看Handler与Looper和MessageQueue之间的关系:
Handler:封装了消息的发送,主要包括了消息发送给谁了
Looper:他的内部包含一个消息队列的的,也就是MessageQueue,也就是,所有的Handler发送的消息都是走向这个消息队列的(sendMessage,这就是证明呀)
他有个重要的方法Looper.Loop:他呢就是一个死循环,不断的从MessageQueue拿消息,如果有消息,那就执行,如果没有消息,那就阻塞、
MessageQueue,根据前面说的,这就是一个消息队列,可以添加消息,并且处理消息。
工作过程:Handler内部会和Looper进行关联,也就是说Handler的内部可以找到Looper ,找到了Looper,也就找到了MessageQueue
,在Handler中发送消息,其实就是想MessageQueue队列中发送消息。
简而言之,Handler负责传送消息,Looper接收Handler传来的消息,MessageQueue就是一堆消息的集合(存储容器)
思路BB完了,现在来看看代码吧
post方法的:
publicclassMainActivityextendsActivity {
privateTextViewtextView;
privateHandlerhandler =newHandler();;
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView= (TextView) findViewById(R.id.TextView1);
newThread() {
@Override
publicvoidrun() {
try{
Thread.sleep(1000);
handler.post(newRunnable() {
@Override
publicvoidrun() {
//这就是更新UI状态,如果不用Handler,那么程序会认为在子线程内部更改UI,程序直接崩溃
textView.setText("Loing for a jab!");
}
});
}catch(InterruptedException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}
}
}.start();
}
}
postDelayed:
publicclassMainActivityextendsActivity {
privateTextViewtextView;
privateHandlerhandler =newHandler();
privateImageViewimageView;
privateintimages[]={R.drawable.tupian1,R.drawable.tupian2,R.drawable.tupian3};
privateMyRunablemyRunable=newMyRunable();
//指定图片在哪个当前位子
privateintindex=0;
classMyRunableimplementsRunnable{
@Override
publicvoidrun() {
index++;
index=index%3;
imageView.setImageResource(images[index]);
handler.postDelayed(myRunable, 1000);//传入的对象,和延期的时间
System.out.println("线程内");
}
}
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView= (TextView) findViewById(R.id.TextView1);
imageView= (ImageView) findViewById(R.id.imageView1);
handler.postDelayed(myRunable, 1000);
System.out.println("线程外");
}
}
sendMessage:
- 以下是Handler进行int型数据传送的方法
-
- 首先就是实例化Handler方法的时候,重写handMessage方法,textView.setText(""+msg.arg1)把要传入的内容显示到text上面
-
- privateHandlerhandler =newHandler(){
publicvoidhandleMessage(android.os.Message msg) {
textView.setText(""+msg.arg1);
};
};
- privateHandlerhandler =newHandler(){
- 然后就是调用这个方法,传送数据
-
- newThread(){
@Override
publicvoidrun() {
try{
Thread.sleep(1000);
Message message=newMessage();
message.arg1=88;
handler.sendMessage(message);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}.start();
- newThread(){
- 以下是进行对象数据的传送
-
- 实例化
-
- private Handler handler=new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
textView.setText(""+msg.obj);
Toast.makeText(getApplicationContext(),""+1,1).show();
return false;
// retunrn true;则下面的的handleMessage就不会进行了
}
}){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(),""+2,1).show();
}
};
- private Handler handler=new Handler(new Handler.Callback() {
- 具体函数
-
- new Thread(){
@Override
public void run() {
try {
Thread.sleep(1000);
Message message=handler.obtainMessage();
User user=new User();
user.age=10;
user.name="HAHA";
message.obj=user;
message.sendToTarget();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
- new Thread(){
自定义与线程相关的Handle这个怎么样:
package com.example.administrator.android_handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
public class SeconActivity extends Activity {
private Handler mhandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Log.d("test","我是主线程:"+Thread.currentThread());
}
};
class MyThread extends Thread{
public Handler handler;
@Override
public void run() {
//创建一个Looper
Looper.prepare();
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
Log.d("test","线程:"+Thread.currentThread());
}
};
Looper.loop();
}
}
private MyThread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView=new TextView(this);
textView.setText("hello handle");
setContentView(textView);
thread=new MyThread();
thread.start();
try {
thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
thread.handler.sendEmptyMessage(1);
mhandler.sendEmptyMessage(1);
}
}
然后即使这个东西HandlerThread:
public class ThreadActivity extends Activity {
private TextView textView;
private HandlerThread handlerThread;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView=new TextView(this);
textView.setText("handler Thread");
setContentView(textView);
handlerThread=new HandlerThread("hander thread");
handlerThread.start();
handler=new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
Log.d("test","线程:"+Thread.currentThread());
Log.d("test","handlerThread.getLooper():"+handlerThread.getLooper());
}
};
handler.sendEmptyMessage(1);
}
}
代码如上,这是正确的写法,可以打印出子线程,好的,如果呢,我们把handler=new Handler(handlerThread.getLooper)改成handler=new Handler()的话,那么显示的就会使主线程了。因为他这个就是直接UI里面创建的Handler。我们再改改,handler=new Handler(handler.getLooper)如果改成这样的话呢,那就直接报错了,错误是,空指针,为啥呢,因为你一个线程创建的时候,内部会和Looper进行关联,但是,你的这个handler=new Handler(handler.getLooper),其实就是一个创建的过程,你程序走到这,你Handler还没有Looper进行关联呢,这可不就是一个空指针嘛 。所以这个方法可以防止多线程并发而导致的空指针问题。
主线程和子线程之间的信息交互:
代码如下:
public class FourActivity extends Activity implements View.OnClickListener {
private Button btSend;
private Button btStop;
private HandlerThread thread;
//这是主线程的创建
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Message message = new Message();
Log.d("test", "线程:" + Thread.currentThread());
Log.d("test", "消息内容:" + message);
threadHandler.sendMessageDelayed(message, 1000);
}
};
private Handler threadHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.four);
btSend = (Button) findViewById(R.id.bt_send);
btStop = (Button) findViewById(R.id.bt_stop);
btSend.setOnClickListener(this);
btStop.setOnClickListener(this);
thread = new HandlerThread("handlerThread");
thread.start();
//子线程的创建
threadHandler = new Handler(thread.getLooper()) {
@Override
public void handleMessage(Message msg) {
Message message = new Message();
handler.sendMessageDelayed(message, 1000);
Log.d("test", "线程:" + Thread.currentThread());
Log.d("test", "消息内容:" + message);
}
};
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_send:
handler.sendEmptyMessage(1);
Log.d("test", "send");
break;
case R.id.bt_stop:
handler.removeMessages(1);
break;
}
}
}
还有就是,我发现这个,循环会一直进行下去,没有办法取消,如果各位亲有发现取消的方法,请告之,谢谢了