Android学习--handler和handlerThread

本文详细解析Android中的Handler机制,包括其如何将消息发送给关联线程并更新UI,以及如何通过runOnUiThread、handlepost、handlesendMessage和viewpost等方法实现UI更新。同时,文章还介绍了Handler的常用方法和使用场景,帮助开发者更高效地管理Android应用中的线程和UI交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

机制要点:

每个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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值