标签:android style java 使用 os io for art
作为Android开发人员,Handler这个类应该是再熟悉不过了,因为几乎任何App的开发,都会使用到Handler这个类,有些同学可能就要说了,我完全可以使用AsyncTask代替它,这个确实是可以的,但是其实AsyncTask也是通过Handler实现的,具体的大家可以去看看源码就行了,Handler的主要功能就是实现子线程和主线程的通信,例如在子线程中执行一些耗时操作,操作完成之后通知主线程跟新UI(因为Android是不允许在子线程中跟新UI的)。
下面就使用一个简单的例子开始这篇文章吧
public class MainActivity extends Activity { public static final int MSG_DOWNLOAD_FINISH=0X001; //创建一个Handler的匿名内部类 private Handler handler=new Handler() { @Override public void handleMessage(Message msg) { switch(msg.what) { case MSG_DOWNLOAD_FINISH: Log.v("yzy", "handler所在的线程id是-->"+Thread.currentThread().getName()); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //启动一个下载线程 public void download(View view) { new Thread() { public void run() { try { Log.v("yzy", "下载子线程的Name是--->"+Thread.currentThread().getName()); //在子线程运行,模拟一个下载任务 Thread.sleep(2000); //下载完成后,发送下载完成消息 handler.sendEmptyMessage(MSG_DOWNLOAD_FINISH); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); }
上面例子就是模拟了一个下载任务,当下载完成后,通过Handler对象发送一个消息,最后被handlerMessage方法接收并处理,通过运行结果可以发现,download方法是在子线程中完成的,而handlerMessage是在UI线程中被调用的。到了这里一个简单的Handler使用案例就结束了,如果你已经明白了上面的代码,那么说明你已经明白了Handler的最基本使用。
下面再来一个简单的例子:
public void postRun(View view) { new Thread(){ public void run() { try { Log.v("yzy", " 下载子线程的Name是--->"+Thread.currentThread().getName()); Thread.sleep(2000); handler.post(new Runnable() { @Override public void run() { Log.v("yzy", "handler post run -->"+Thread.currentThread().getName()); } }); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); }
在Handler中除了可以发送Message对象还可以发送Runnable对象,从运行结果来看发送的Runnable也是在main线程中执行的
那么是不是通过handler发出的Message和Runnable都是在UI线程中执行的呢,这个可不一定,现在我在onCreate方法中创建一个handler2
HandlerThread thread=new HandlerThread("yzy"); thread.start(); handler2=new Handler(thread.getLooper()) { public void handleMessage(Message msg) { switch(msg.what) { case MSG_DOWNLOAD_FINISH: Log.v("yzy", "handler所在的线程Name是-->"+Thread.currentThread().getName()); break; } }; };
//无参构造函数 public Handler() { //检查Handler是否是static的,如果不是的,那么有可能导致内存泄露,具体可以百度 if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } //很重要的一个属性,暂时就将Looper理解成一个消息队列的管理者吧,用来从消息队列中取消息的,稍后会分析这个类 mLooper = Looper.myLooper(); if (mLooper == null) { //这个异常非常常见哦,Handler一定要在有Looper的线程上执行,这个也就是为什么我在HandlerThread中初始化Handler //而没有在Thread里面初始化,如果在Thread里面初始化需要先调用Looper.prepare方法 throw new RuntimeException( "Can‘t create handler inside thread that has not called Looper.prepare()"); } //将mLooper里面的消息队列复制到自身的mQueue,这也就意味着Handler和Looper是公用一个消息队列 mQueue = mLooper.mQueue; //回调函数默认是Null mCallback = null; } //这个和上面一样的,只不过传入了一个回调函数 public Handler(Callback callback) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can‘t create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; } /** * 传入一个Looper,并和Looper公用一个消息队列 */ public Handler(Looper looper) { mLooper = looper; mQueue = looper.mQueue; mCallback = null; } /** * 和上面一个差不多,就不在赘述 */ public Handler(Looper looper, Callback callback) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; }
* class LooperThread extends Thread { * public Handler mHandler; * * public void run() { * Looper.prepare(); * * mHandler = new Handler() { * public void handleMessage(Message msg) { * // process incoming messages here * } * }; * * Looper.loop(); * } *
//Looper的构造函数,主要是对消息队列等属性初始化 private Looper() { mQueue = new MessageQueue(); mRun = true; //记录所在线程 mThread = Thread.currentThread(); } //在上面的例子中,看到当在一个没有Looper的线程中创建Handler,就需要执行这个函数, //这个函数主要是new 一个Looper,燃火放入ThreadLocal中保存,做到一个线程就创建一次。第二次调用这个方法会抛出异常的 public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } //prepare是创建并保存,这个方法就是取出Looper public static final Looper myLooper() { return (Looper)sThreadLocal.get(); } //这个方法是给系统调用的,UI线程通过调用这个线程,从而保证UI线程里有一个Looper //需要注意:如果一个线程是UI线程,那么myLooper和getMainLooper是同一个Looper,通过这个代码很好理解 public static final void prepareMainLooper() { prepare(); setMainLooper(myLooper()); if (Process.supportsProcesses()) { myLooper().mQueue.mQuitAllowed = false; } } //获得UI线程的Looper,通常我想Hanlder的handleMessage在UI线程执行时通常会new Handler(getMainLooper()); public synchronized static final Looper getMainLooper() { return mMainLooper; } /** * 上面的例子是执行了这个方法的,这个方法是一个死循环,一直从消息队列中读取消息,并分发出去 */ public static final void loop() { //得到本线程的Looper Looper me = myLooper(); //拿到消息队列 MessageQueue queue = me.mQueue; while (true) { //从消息队列中拿一个消息 Message msg = queue.next(); // might block //取到了一个消息 if (msg != null) { //这个一般不等于Null,通常就是发出这个Message的Handler if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); //调用Handler的dispatchMessage方法 msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); //将消息放入消息池 msg.recycle(); } } } //返回Looper的消息队列 public static final MessageQueue myQueue() { return myLooper().mQueue; }
//在Handler中发送一个消息到消息队列,类似的方法很多,我只选了这一个 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { //将target设置成了Handler msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } //这个方法是在loop方法中被调用的 public void dispatchMessage(Message msg) { //首先检查msg中callback(是一个Runnable对象)是否为Null,如果不为null,则直接调用callback中的run方法 if (msg.callback != null) { handleCallback(msg); } else { //检查Handler中的callback是否为空,如果不为空,则直接调用callback中的handleMessage,如果返回TRUE,则直接返回不在调用Handler中的handleMessage if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } //最后调用Handler中的handlerMessage handleMessage(msg); } }
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private final Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
//让Runnable在UI线程执行 public final void runOnUiThread(Runnable action) { //如果当前线程不是UI线程,那么通过Handler转发到UI线程 if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); } }
public boolean post(Runnable action) { Handler handler; if (mAttachInfo != null) { handler = mAttachInfo.mHandler; } else { // Assume that post will succeed later ViewRoot.getRunQueue().post(action); return true; } return handler.post(action); }
Android Handler消息机制深入浅出,布布扣,bubuko.com
标签:android style java 使用 os io for art
原文地址:http://blog.csdn.net/yuanzeyao/article/details/38408493