Handler 的应用场景个人总结学习

        前面二篇都是关于 Handler message  Thread  runnable 文章,大概从源代码和流程机制 三者的关系。接下来谈谈应用场景。Handler 就是为了实现多线程的问题,前面一篇文章也讲过,多线程并发有一定的缺陷,android 引入message机制就很好的解决了多线程并发问题了。假设在一个activity里面有多个线程去更新UI,并且都没有加锁机制,那就会造成更新UI错乱。如果对更新UI的操作都进行加锁处理,就会造成性能下降。使用消息机制,根本不用关系多线程的问题,因为更新UI的操作,都是在主线程的消息队列当中去轮询处理的。这里也特别强调下,在UI Thread 更新UI。

      Handler既然是android只带的消息机制,那我们就可以通过handler 来发消息和处理消息。下面来讲讲Handler应用场景。

应用场景一:刷新UI界面。


<pre name="code" class="java">public class HandlerActivity extends Activity implements OnClickListener {
	private static final String TAG = "stvelzhang";
    private TextView tv_activity_test_update_ui ;
    private Button btn_handler1, btn_handler2,btn_handler3,btn_handler4;
    private static final int SUCCESS_GET_DATA = 1;
    private static final int SUCCESS_GET_DATA_OBJ = 2;
    private static final int SUCCESS_GET_DATA_BUNDLE = 3;
    private Handler mHandler = new Handler();
    private Handler myHandler = new Handler(){
    	@Override
    	public void handleMessage(Message msg) {
    		super.handleMessage(msg);
    		switch(msg.what){
    		case SUCCESS_GET_DATA:
    			Log.d(TAG,"myhandler thread_id :: " + Thread.currentThread().getId()
    					+ "  myhandler thread_name :: " 
    					+ Thread.currentThread().getName());
    			//打印显示  myhandler thread_id :: 1  myhandler thread_name :: main
    			tv_activity_test_update_ui.setText("使用handler.sendMessage()更新");
    			break;
    		case SUCCESS_GET_DATA_OBJ:
 
    			tv_activity_test_update_ui.setText("使用handler.sendMessage()更新" + msg.obj);
    			break;

    		case SUCCESS_GET_DATA_BUNDLE:
    			Bundle date = msg.getData();

    			
    			tv_activity_test_update_ui.setText("使用handler.sendMessage()更新" + " :: " + date.getInt("year") + " :: " + date.getString("where"));
    			break;
    			
    		}
    	}
    	
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv_activity_test_update_ui = (TextView) findViewById(R.id.tv_update_ui);
        initview();
        Log.d(TAG,"activity thread_id :: " + Thread.currentThread().getId()
				+ "  activity thread_name :: " 
				+ Thread.currentThread().getName());
    }

    public void initview(){
    	btn_handler1 = (Button) findViewById(R.id.btn_1);
    	btn_handler1.setOnClickListener(this);
    	btn_handler2 = (Button) findViewById(R.id.btn_2);
    	btn_handler2.setOnClickListener(this);
    	btn_handler3 = (Button) findViewById(R.id.btn_3);
    	btn_handler3.setOnClickListener(this);
    	btn_handler4 = (Button) findViewById(R.id.btn_4);
    	btn_handler4.setOnClickListener(this);
    	
    }

	@Override
	public void onClick(View vid) {
		switch(vid.getId()){
		case R.id.btn_1:
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					runOnUiThread(new Runnable(){

						@Override
						public void run() {
							tv_activity_test_update_ui.setText("调用runOnUIThread方法更新"); 
						}
						
						
					});
				}
			}).start();
			
			/*
			  new Thread(new Runnable(){

				@Override
				public void run() {
					Log.d(TAG,"btn1 thread_id :: " + Thread.currentThread().getId()
							+ "  btn1 thread_name :: " 
							+ Thread.currentThread().getName());
					tv_activity_test_update_ui.setText("调用runOnUIThread方法更新"); 
				}
				  
				  
			  }).start();
			  
			  *上面的代码运行会报错 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
			  *说明只能在程序的主线程(也就是ui Thread)线程中进行更新界面显示的工作
			  *
			  */
			  
			break;
		case R.id.btn_2:
			tv_activity_test_update_ui.post(new Runnable(){

				@Override
				public void run() {
					Log.d(TAG,"btn2 thread_id :: " + Thread.currentThread().getId()
							+ "  btn2 thread_name :: " 
							+ Thread.currentThread().getName());
					//打印出来是  btn2 thread_id :: 1  btn2 thread_name :: main
					//说明是Ui线程,所以可以更新UI。
					tv_activity_test_update_ui.setText("使用View的post()更新UI");
				}
				
				
			});
			break;
		case R.id.btn_3:
			new Thread(new Runnable(){

				@Override
				public void run() {
					Log.d(TAG,"btn3 thread_id :: " + Thread.currentThread().getId()
							+ "  btn3 thread_name :: " 
							+ Thread.currentThread().getName());
					//打印出来  btn3 thread_id :: 682  btn3 thread_name :: Thread-682
					//说明线程是用了new thread。这也符合情况。
					mHandler.post(new Runnable(){

						@Override
						public void run() {
							tv_activity_test_update_ui.setText("Handler的post()更新UI");
							Log.d(TAG,"getcurrent thread_id :: " + Thread.currentThread().getId()
									+ "  getcurrent thread_name :: " 
									+ Thread.currentThread().getName());
							//打印出来  getcurrent thread_id :: 1  getcurrent thread_name :: main
							//mHandler 是在主线程定义声明的。handler 和 线程是绑定在一起的。
							//这个例子也正好证明了,可以在子线程通过handler 对UI 进行刷新。
						}
						
						
					});
				}
				
				
			}).start();
			break;
		case R.id.btn_4:
			new Thread(new Runnable(){

				@Override
				public void run() {
					
					myHandler.sendEmptyMessage(SUCCESS_GET_DATA);
					
					/*
					 * 上面send empty message,没有带数据的。下面带上数据
					 * (1) Message 对象
					 * message 对象携带数据,通常用 arg1 arg2 来传递消息数据,也可以使用obj参数,也可以使用 bundle数据。
					 * Message msg = handler.obtainMessage();
					 * (2) Bundle 对象
					 * Bundle 是一个类,可以看着map一样的东西,有key 有数据。key 必须是String 类型。
					 
					Message msg = myHandler.obtainMessage();
					//华丽的分割线					
					msg.obj = "tiger is here";
					msg.what = SUCCESS_GET_DATA_OBJ;
					myHandler.sendMessage(msg);
					
					//华丽的分割线
					msg.what = SUCCESS_GET_DATA_BUNDLE;
					Bundle bud = new Bundle();
					bud.putInt("year", 2016);
					bud.putString("where", "北方的狼");
					msg.setData(bud);
					msg.sendToTarget();
					
					*/					
					Log.d(TAG,"btn4 thread_id :: " + Thread.currentThread().getId()
							+ "  btn4 thread_name :: " 
							+ Thread.currentThread().getName());
					//打印显示 btn4 thread_id :: 691  btn4 thread_name :: Thread-691
					//如果在这里直接写 tv_activity_test_update_ui.setText("使用handler.sendMessage()更新");
					//肯定是要报错的。因为是子线程了
				}

			}).start();
			break;
		
		}
		
	}
   
}


 
应用场景二:自定义与线程相关的handler 

在一个子线程中去创建一个Handler,然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行

 new Thread()
{
	private Handler handler;
	public void run()
	{
		Looper.prepare();
		handler = new Handler()
		{
			public void handleMessage(android.os.Message msg)
			{
				Log.d(TAG,Thread.currentThread().getName());
			};
		}; 
                Looper.loop();
	}  
}



public class ThreadDemo extends Activity {
	private static final String TAG = "ThreadDemo";
	private static final int UI_HANDLER_MSG = 1;
	private static final int THREAD_HANDLER_MSG = 2;
	private MyThread myThread;
	private Handler mHandler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch(msg.what){
			
			case UI_HANDLER_MSG:
				Log.d(TAG, "mHandler threadid :: " +
					Thread.currentThread().getId() + 
					"  mHandler threadname :: " + 
					Thread.currentThread().getName());
				Log.d(TAG, " I am come UI handler done message");
				break;

			}
		}
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.lay_thread);
		myThread = new MyThread();
		myThread.start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		mHandler.sendEmptyMessage(UI_HANDLER_MSG);
		myThread.myHandler.sendEmptyMessage(THREAD_HANDLER_MSG);
	}
	
    class  MyThread extends Thread{
    	private Handler myHandler;
    	
    	
		@Override
		public void run() {
			super.run();
			Looper.prepare();
			myHandler = new Handler(){
				@Override
				public void handleMessage(Message msg) {
					super.handleMessage(msg);
					//we can do something ......
					Log.d(TAG,"getcurrent threadid :: " +
					Thread.currentThread().getId() + 
					"  getcurrent threadname :: " + 
					Thread.currentThread().getName());
					
					switch(msg.what){
					case THREAD_HANDLER_MSG:
						Log.d(TAG, " I am come myhandler done message");
						break;
					}
				}
				
			};
			
			Looper.loop();
			
			
		}
		
		
	}
}

打印显示 : 

D/ThreadDemo(29475): getcurrent threadid :: 936  getcurrent threadname :: Thread-936

D/ThreadDemo(29475):  I am come myhandler done message
D/ThreadDemo(29475): mHandler threadid :: 1  mHandler threadname :: main

D/ThreadDemo(29475):  I am come UI handler done message


不同的线程handler 消息处理是不一样的。

应用场景三:定时器

private static final int LOAD_DISPLAY_TIME = 3000; // 延迟3s
 
new Handler().postDelayed(new Runnable() {
	public void run() {
	// 时间到时,执行的代码
	}
}, LOAD_DISPLAY_TIME);
 
关闭此定时器:handler.removeCallbacks(runnable);


一个activity 延时 然后跳转到 其他activity,引导应用首页

private void startThreadDemo() {
    	mHandler.postDelayed(new Runnable(){

			@Override
			public void run() {
				Intent mintent = new Intent(HandlerActivity.this, ThreadDemo.class);
				startActivity(mintent);
				HandlerActivity.this.finish();
			}
    		
    	}, 1000);
	}

应用场景四:拦截Handler传递的消息

public class CallBackDemo extends Activity implements OnClickListener {
	
	private Button btn1, btn2;
	private TextView tv_1, tv_2;
	private Handler mHandler = new Handler(new Handler.Callback() {
		
		@Override
		public boolean handleMessage(Message arg0) {
			Toast.makeText(CallBackDemo.this, R.string.hello_callback, 
            		Toast.LENGTH_SHORT);
			Log.d("CallBackDemo", "handleMessage msg ::  " + arg0.what);
			tv_1.setText("callback handlermessage msg :: " + arg0.what);
			tv_2.setText("callback handlermessage msg :: " + arg0.what);
			if(arg0.what == 0x01){
			return false;
			}
			else{
			return true;
			}
		}
	}){
        @Override
        public void handleMessage(Message msg) {
            Toast.makeText(CallBackDemo.this, R.string.hello_callback_ui, 
            		Toast.LENGTH_LONG);
            tv_2.setText("handlermessage msg :: " + msg.what);
            tv_1.setText(R.string.dont_intercept_msg);
        }
    };
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.lay_callback);
		initview();
	}
	
	public void initview(){
		tv_1 = (TextView) findViewById(R.id.tv_dont_ui);
		tv_2 = (TextView) findViewById(R.id.tv_done_ui);
		btn1 = (Button) findViewById(R.id.btn_dont);
		btn2 = (Button) findViewById(R.id.btn_done);
		btn1.setOnClickListener(this);
		btn2.setOnClickListener(this);
		
	}

	@Override
	public void onClick(View view) {
		switch(view.getId()){
		
		case R.id.btn_dont:
			Log.d("CallBackDemo", "onclick btn_dont");
			mHandler.sendEmptyMessage(0x01);
			break;
		case R.id.btn_done:
			Log.d("CallBackDemo", "onclick btn_done");
			mHandler.sendEmptyMessage(0x02);
			break;
		}

		
	}
	
}

最后附上代码参考学习下。

本篇文章的源代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值