标签:
Android的消息机制主要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。对于有开发过Android经验的童鞋都知道,我们一般都是用Handler来更新UI的,更新UI只是handler用法的一部分,下面一起来研究一下handler的神秘面纱。
那么handler是什么?
handler是android给我们用来更新UI的一套机制,也是一套消息处理机制,我们可以通过handler来发送消息,也可以通过它来处理消息
handler主要有以下4种用法
1、sendMessage
2、sendMessageDelayed
3、post(Runnable)
4、postDelayed(Runnable,long)
sendMessage
public class MainActivity extends Activity implements View.OnClickListener { private Button btn1; private Button btn2; private Handler handler = new Handler(){ //这种方式我们在开发中用的比较多,在主线程中去更新UI @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.v("hjz","执行了handleMessage"); } }; private Handler handler1 = new Handler(new Handler.Callback() { //创建一个回调Callback,并实现handleMessage @Override public boolean handleMessage(Message msg) { Log.v("hjz","执行了Callback里面的handleMessage"); /** * 返回false,说明事件继续向下分发,继续调用下面的handleMessage方法 * 返回true,说明自己消耗此事件,到此就结束了,起到拦截作用 * 这种用法似曾相识吧,不错,跟ViewGroup分发事件很类似 */ return false; } }){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.v("hjz","执行了handleMessage"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); setLister(); } private void initView() { btn1 = (Button) findViewById(R.id.btn1); btn2 = (Button) findViewById(R.id.btn2); } private void setLister() { btn1.setOnClickListener(this); btn2.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn1: new Thread(new Runnable() { @Override public void run() { Message msg = handler.obtainMessage(); msg.what = 1; handler.sendMessage(msg); } }).start(); break; case R.id.btn2: new Thread(new Runnable() { @Override public void run() { Message msg = handler1.obtainMessage(); msg.what = 1; handler1.sendMessage(msg); } }).start(); break; } } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical"> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="handler"/> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="handler1"/> </LinearLayout>在Callback中handleMessage返回值为false时,点击btn1 和 btn2打印日志:
07-19 21:16:31.091 9943-9943/com.example.handlerdemo V/hjz: 执行了handleMessage 07-19 21:16:34.341 9943-9943/com.example.handlerdemo V/hjz: 执行了Callback里面的handleMessage 07-19 21:16:34.341 9943-9943/com.example.handlerdemo V/hjz: 执行了handleMessage
07-19 21:23:18.991 22980-22980/com.example.handlerdemo V/hjz: 执行了handleMessage 07-19 21:23:20.901 22980-22980/com.example.handlerdemo V/hjz: 执行了Callback里面的handleMessage从打印的日志中也验证了在上面handler1的分析
sendMessageDelayed
case R.id.btn1: new Thread(new Runnable() { @Override public void run() { Message msg = handler.obtainMessage(); msg.what = 1; /** * 第一个参数是一个Message对象 * 第二次参数是延迟时间(单位毫秒) */ handler.sendMessageDelayed(msg,1000); } }).start(); break;
post(Runnable)
private Handler postHandler = new Handler(); private void setPost(){ new Thread(new Runnable() { @Override public void run() { postHandler.post(new Runnable() { @Override public void run() { Log.v("hjz","postHandler"); } }); } }).start(); }
private Handler postDelayedHandler = new Handler(); private void setPostDelayed(){ new Thread(new Runnable() { @Override public void run() { postDelayedHandler.postDelayed(new Runnable() { @Override public void run() { Log.v("hjz","postDelayedHandler"); } },1000); } }).start(); }
接着我们一起分析Handler创建,看一下Handler的构造函数
public Handler() { this(null, false); }
public Handler(Callback callback, boolean async) { 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(); //获取一个Looper对象,那么Looper在什么时候被创建呢? if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }通过源码ActivityThread中main方法
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Environment.initForCurrentUser(); // Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter()); AndroidKeyStoreProvider.install(); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Looper.prepareMainLooper();//这句话创建了一个Looper对象,通过Looper构造方法创建一个MessageQueue对象,并将Looper对象存储在ThreadLocal集合中,供后面在Handler创建时获取对应的Looper对象(需注意拿到对应Looper对象也能拿到Looper对应的MessageQueue对象) ActivityThread thread = new ActivityThread(); //创建ActivityThread对象 thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled(); } }); android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } // Watch for getting close to heap limit. BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { } } } }); } else { // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId()); try { mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); mInitialApplication = context.mPackageInfo.makeApplication(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate Application():" + e.toString(), e); } } // add dropbox logging to libcore DropBox.setReporter(new DropBoxReporter()); //重点来看这里 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { @Override public void onConfigurationChanged(Configuration newConfig) { synchronized (mResourcesManager) { // We need to apply this change to the resources // immediately, because upon returning the view // hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) { // This actually changed the resources! Tell // everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(newConfig)) { mPendingConfiguration = newConfig; //通过一个handler来切换整个activity的生命周期,并实现将handle存储在MessageQueue中 sendMessage(H.CONFIGURATION_CHANGED, newConfig); } } } } @Override public void onLowMemory() { } @Override public void onTrimMemory(int level) { } }); }
通过对源码的分析,我们知道Looper创建是在Acitivity开始启动时就创建了
Looper、MessageQueue和Handler的关系
Looper
1、内部包含一个消息队列(MessageQueue),所有的Handler发送消息都走这个消息队列
2、Looper.Looper方法,就是一个死循环,不断从MessageQueue中取消息,如果有消息就处理消息,没有消息就进入阻塞
MessageQueue
MessageQueue就是一个消息队列,可以添加消息,并可以处理消息
Handler
Handler内部跟Looper进行关联,也就是说在Handler的内部可以找到Looper,找到Looper也就可以找到了MessageQueue;在Handler中发送消息,其实就是向MessageQueue队列中发送消息
总结一下三者的关系:handler负责发送消息,Looper负责接收Handler发送过来的消息,并直接把消息回传给handler本身,MessageQueue就是一个存储消息的容器
先写到这里先,后续会继续去完善
标签:
原文地址:http://blog.csdn.net/zjws23786/article/details/51946371