机制要点:
每个Handler的实例都关联了一个线程和线程的消息队列。当创建了一个Handler对象时,一个线程或消息队列同时也被创建,该Handler对象将发送和处理这些消息或Runnable对象。采用默认构造函数意味着自动与主线程关联,系统为主线程自动创建了Looper,MessageQueue。那么简而言之,handler的作用是将消息发送给关联的线程,在关联线程中运行关联线程的run方法,因此如果handler和主线程关联了,那么自然可以更新主线程的UI了啊~~~~
常见更新UI的方法:
1、runOnUiThread
2、handle post
利用runnable执行时,相当于直接调用runnable中的run方法,可以不启动线程。
3、handle sendMessage
3.1在主线程中声明创建handler,并且重写handleMessage方法
3.2在子线程中声明线程,run方法中利用handler调用sendMessage方法
3.3在主线程中启动子线程,调用start方法
4、view post
方法:
1.post/postDelayed
2.sendMessage
public class MainActivity extends Activity {
//private MyThread thread;
private Handler handler=new Handler()//默认构造函数与主线程关联
{
public void handleMessage(Message msg)//主线程处理消息
{
//Toast.makeText(getApplicationContext(), ""+2, 1).show();
tv.setText("继承Thread的线程结合handler");
}
};
private MyRunnable myRunnable;
private TextView tv;
private int index=0;
class MyRunnable implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
index++;
tv.setText(index+"");
Log.i("tv",tv.getText().toString());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.postDelayed(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
tv.setText("运行一次");
}
},1000);
}
}
class MyThread extends Thread
{
@Override
public void run() {
// TODO Auto-generated method stub
//super.run();
handler.sendEmptyMessage(1);//子线程中发送消息
};
//}
}//Thread类结束*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.tv);
//开启了两个线程,分别使用的是runnable+handler+post,thread+handler+sendMessage方法,其实都可以互换的,本质是Thread + handler +post/sendMessage
myRunnable =new MyRunnable();
Thread thread=new Thread(myRunnable);
thread.start();
MyThread my=new MyThread();
my.start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
注意:如果改变postDelayed语句中的Runnable对象,那么会反复调用myRunnable中的run方法,不断用handler修改UI线程
private MyRunnable myRunnable;
private TextView tv;
private int index=0;
class MyRunnable implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
index++;
tv.setText(index+"");
Log.i("tv",tv.getText().toString());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.postDelayed(myRunnable,1000);
}
}
注意:直接利用handler对象post了一个runnable对象,相当于直接调用了Runnable对象的run函数,也就说没有经过start函数调用run(),那么就不会创建一个新线程,而是在原有线程内部直接调用 run()方法,打印子线程ID和主线程ID会发现是相同的。
public class MainActivity extends Activity {
private Handler handler=new Handler(/*thread.looper*/)
{
public void handleMessage(Message msg)
{
//Toast.makeText(getApplicationContext(), ""+2, 1).show();
tv.setText("runnable构造的线程结合handler");
}
};
private MyRunnable myRunnable;
private TextView tv;
private int index=0;
class MyRunnable implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
index++;
tv.setText(index+"");
Log.i("tv",tv.getText().toString());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.postDelayed(myRunnable,1000);//反复调用myRunnable的run方法
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.tv);
myRunnable =new MyRunnable();//没有调用runnable的start方法照样可以运行相同效果
handler.post(myRunnable);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
注意:希望new一个带参构造函数的Handler对象,那么这个Handler对象将与参数所表示的Looper相关联。注意:此时线程类应该是一个特殊类HandlerThread类,它继承自Thread类。
HandlerThread的使用1
HandlerThread my=new HandlerThread("MyThread"); //构造方法中必须有string name
my.start();//启动线程
//利用子线程的looper构造与本线程相关联的handler
Handler myHandler=new Handler(my.getLooper()){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i("my", "MyHandler-->handleMessage-->threadid = " + Thread.currentThread().getName());
}
};
myHandler.sendEmptyMessage(1);//向子线程发送
子线程和主线程的交互
public class FromMainThread extends Activity implements OnClickListener {
private Handler handler =new Handler(){
public void handleMessage(Message msg)
{
System.out.println("main handler");
Message msg2=new Message();
//主线程向子线程发送消息
threadHandler.sendMessageDelayed(msg2, 1000);
}
};
private Handler threadHandler;
private Button but1;
private Button but2;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.frommainthread);
HandlerThread thread=new HandlerThread("my");
thread.start();
threadHandler=new Handler(thread.getLooper())
{
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
//super.handleMessage(msg);
System.out.println("threadhandler");
Message msg1=new Message();
//子线程向主线程发送消息
handler.sendMessageDelayed(msg1, 1000);//主线程的handler
}
};
but1=(Button)findViewById(R.id.button1);
but2=(Button)findViewById(R.id.button2);
but1.setOnClickListener(this);
but2.setOnClickListener(this);
}
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
switch(arg0.getId())
{
case(R.id.button1):
handler.sendEmptyMessage(1);
break;
case(R.id.button2):
handler.removeMessages(1);
break;
}
}
}
总结:handler采用默认构造函数则表示与主线程关联,否则采用handlerThread的getLooper进行初始化,与该子线程关联。调用handler发送消息,就在构造handler的线程中运行handleMessage