Android Handler、Message 常用方法

前言

本文简记 Handler 以及 Message 的常用方法。

Handler

事件计划

  • 常用 postDelayed() 方法。

  • 示例:

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
    	@Override
    	public void run() {
    		Toast.makeText(getApplicationContext(), "3000毫秒事件计划", Toast.LENGTH_LONG).show();
    	}
    }, 3000);
    

线程间通信

最简单

  • 示例:

    Handler handler = new Handler() {
    	@Override
    	public void handleMessage(@NonNull Message msg) {
    		super.handleMessage(msg);
    		switch (msg.what) {
    			case 1:
    				Toast.makeText(getApplicationContext(), "线程间通信成功", Toast.LENGTH_LONG).show();
    				break;
    		}
    	}
    };
    
    new Thread() {
    	@Override
    	public void run() {
    		super.run();
    		Message message = new Message();
    		message.what = 1;
    		handlerMsg.sendMessage(message);
    	}
    }.start();
    
  • 但是这样的写法已经被弃用了。

避免内存泄露

  • 上一点最简单的写法会造成内存泄露,使得程序或系统崩溃,以及存在安全隐患。
  • 这里记录相对来说比较好理解、相对简单的写法,更多的方法看文档。
继承 Handler 的静态子类
  • 示例:

    首先在实现子线程 new Thread() 的方法外写一个继承 Handler 的静态子类:

    private static class HandlerMsg extends Handler {
    	@Override
    	public void handleMessage(@NonNull Message msg) {
    		super.handleMessage(msg);
    		switch (msg.what) {
    			case 10001:i
    				Log.i(">>>>==== GET HandlerMsg ====<<<< : ", "msg.what = "+msg.what+", obj = "+(String)msg.obj);
    				break;
    		}
    	}
    }
    

    然后在子线程 new Thread() 所在的方法下声明该类的对象,再在子线程 new Thread() 中调用:

    public void threadSendMsg() {
    	final HandlerMsg handlerMsg = new HandlerMsg();
    	new Thread() {
    		@Override
    		public void run() {
    			super.run();
    			Message message = new Message();
    			message.what = 10001;
    			message.obj = "yogile";
    			handlerMsg.sendMessage(message);
    		}
    	}.start();
    }
    
  • threadSendMsg() 通过按钮控件触发,运行结果:

    2020-07-08 19:25:39.862 5901-5901/com.yogile.running D/>>>>==== GET HandlerMsg ====<<<< : msg.what = 1, obj = yogile
    
Handler 对象回调
  • 可以使用 Callback() 实现 线程间的即时数据通信。

  • 示例:

    threadSendMsg() 可以不变化,setHandler() 可在 onCreate() 中并在 threadSendMsg() 之前调用。

    public class MainActivity extends AppCompatActivity {
    	......
    	Handler handler;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		......
    		setHandler();
    		......
    	}
    
    	/**
    	 * 初始化 handler
    	 */
    	private void setHandler() {
    		handler = new Handler(new Handler.Callback() {
    			@SuppressLint("LongLogTag")
    			@Override
    			public boolean handleMessage(@NonNull Message message) {
    				switch (message.what) {
    					case 1001:
    						Log.d(">>>>==== GET HandlerMsg ====<<<< : ", "msg.what = "+msg.what+", obj = "+(String)msg.obj);
    						break;
    					default:
    						throw new IllegalStateException("Unexpected value: " + message.what);
    				}
    				return false;
    			}
    		});
    	}
    
    	public void threadSendMsg() {
    		final HandlerMsg handlerMsg = new HandlerMsg();
    		new Thread() {
    			@Override
    			public void run() {
    				super.run();
    				Message message = new Message();
    				message.what = 10001;
    				message.obj = "yogile";
    				handlerMsg.sendMessage(message);
    			}
    		}.start();
    	}
    }
    

Message

对象声明

  • Message 有多种构造方法:

    Message message = new Message();
    Message message = Message.obtain();
    等待
    

    通过 Message.obtain() 声明一个 Message 的对象,比直接 new Message() 的性能更好,可以避免声明重复的对象。

常用方法

public 变量

  • 通过 what、obj 等 Message 中固有的 public 变量,传递信息。

set/getData()

  • 可以使用 setData() 将 Bundle 类型的数据存放在 message 中。
  • 可以使用 getData() 获得存放在 message 中的 Bundle 类型数据。

发送

  • 通过 handler 对象的 sendMessage() 方法发送 message 。
posted @ 2020-07-08 19:44  Yogile  阅读(301)  评论(0编辑  收藏  举报