一般æ¥è¯ß_¼Œè‡ªå®šä¹‰æŽ§ä»‰™ƒ½ä¼šåŽ»é‡å†™Viewçš„onMeasureæ–ÒŽ(gu¨©)³•åQŒå› 䏸™¯¥æ–ÒŽ(gu¨©)³•指定该控件在å±å¹•上的大å°ã€?/p>
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
onMeasureä¼ å…¥çš„ä¸¤ä¸ªå‚æ•°æ˜¯ç”׃¸Šä¸€å±‚æŽ§ä»¶ä¼ å…¥çš„å¤§å°åQŒæœ‰å¤šç§æƒ…况åQŒé‡å†™è¯¥æ–ÒŽ(gu¨©)³•æ—‰™œ€è¦å¯¹è®¡ç®—控äšg的实际大ž®ï¼Œç„¶åŽè°ƒç”¨setMeasuredDimension(int, int)讄¡½®å®žé™…大å°ã€?/p>
onMeasureä¼ å…¥çš„widthMeasureSpecå’ŒheightMeasureSpec䏿˜¯ä¸€èˆ¬çš„ž®ºå¯¸æ•°å€û|¼Œè€Œæ˜¯ž®†æ¨¡å¼å’Œž®ºå¯¸¾l„åˆåœ¨ä¸€èµïLš„æ•°å€¹{€‚我们需è¦é€šè¿‡int mode = MeasureSpec.getMode(widthMeasureSpec)得到模å¼åQŒç”¨int size = MeasureSpec.getSize(widthMeasureSpec)得到ž®ºå¯¸ã€?/span>
modeå…±æœ‰ä¸‰ç§æƒ…况åQŒå–å€¼åˆ†åˆ«äØ“MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOSTã€?/span>
MeasureSpec.EXACTLY是精¼‹®å°ºå¯¸ï¼Œå½“我们将控äšgçš„layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip"åQŒæˆ–è€…äØ“FILL_PARENT是,都是控äšg大å°å·²ç»¼‹®å®šçš„æƒ…况,都是¾_„¡¡®ž®ºå¯¸ã€?/span>
MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENTæ—Óž¼ŒæŽ§äšg大å°ä¸€èˆ¬éšç€æŽ§äšgçš„å½Iºé—´æˆ–内容进行å˜åŒ–ï¼Œæ¤æ—¶æŽ§äšgž®ºå¯¸åªè¦ä¸è¶…˜q‡çˆ¶æŽ§äšgå…许的最大尺寸å³å¯ã€‚å› æ¤ï¼Œæ¤æ—¶çš„mode是AT_MOSTåQŒsize¾l™å‡ºäº†çˆ¶æŽ§äšgå…许的最大尺寸ã€?/p>
MeasureSpec.UNSPECIFIED是未指定ž®ºå¯¸åQŒè¿™¿U情况ä¸å¤šï¼Œä¸€èˆ¬éƒ½æ˜¯çˆ¶æŽ§äšg是AdapterViewåQŒé€šè¿‡measureæ–ÒŽ(gu¨©)³•ä¼ å…¥çš„æ¨¡å¼ã€?/p>
å› æ¤åQŒåœ¨é‡å†™onMeasureæ–ÒŽ(gu¨©)³•æ—¶è¦æ ÒŽ(gu¨©)®æ¨¡å¼ä¸åŒ˜q›è¡Œž®ºå¯¸è®¡ç®—。下é¢ä»£ç 就是一¿U比较典型的方å¼åQ?br />
Android¾pÈ»Ÿä¸Looperè´Ÿè´£½Ž¡ç†¾U¿ç¨‹çš„æ¶ˆæ¯é˜Ÿåˆ—和消æ¯å¾ªçޝåQŒå…·ä½“实现请å‚考Looperçš„æºç ã€?å¯ä»¥é€šè¿‡Loop.myLooper()得到当剾U¿ç¨‹çš„Looper对象åQŒé€šè¿‡Loop.getMainLooper()å¯ä»¥èŽ·å¾—å½“å‰˜q›ç¨‹çš„主¾U¿ç¨‹çš„Looper对象ã€?/font>
å‰é¢æåˆ°Android¾pÈ»Ÿçš„æ¶ˆæ¯é˜Ÿåˆ—和消æ¯å¾ªçŽ¯éƒ½æ˜¯é’ˆå¯¹å…·ä½“¾U¿ç¨‹çš„,一个线½E‹å¯ä»¥å˜åœ¨ï¼ˆå½“然也å¯ä»¥ä¸å˜åœ¨åQ‰ä¸€ä¸ªæ¶ˆæ¯é˜Ÿåˆ—和一个消æ¯åó@环(LooperåQ‰ï¼Œç‰¹å®š¾U¿ç¨‹çš„æ¶ˆæ¯åªèƒ½åˆ†å‘给本线½E‹ï¼Œä¸èƒ½˜q›è¡Œè·¨çº¿½E‹ï¼Œè·¨è¿›½E‹é€šè®¯ã€‚但是创建的工作¾U¿ç¨‹é»˜è®¤æ˜¯æ²¡æœ‰æ¶ˆæ¯åó@环和消æ¯é˜Ÿåˆ—的,如果惌™®©è¯¥çº¿½E‹å…·æœ‰æ¶ˆæ¯é˜Ÿåˆ—和消æ¯å¾ªçޝåQŒéœ€è¦åœ¨¾U¿ç¨‹ä¸é¦–先调用Looper.prepare()æ¥åˆ›å»ºæ¶ˆæ¯é˜Ÿåˆ—,然åŽè°ƒç”¨Looper.loop()˜q›å…¥æ¶ˆæ¯å¾ªçŽ¯ã€‚å¦‚ä¸‹ä¾‹æ‰€½Cºï¼š
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(); } }
˜q™æ ·ä½ çš„¾U¿ç¨‹ž®±å…·æœ‰äº†æ¶ˆæ¯å¤„ç†æœºåˆ¶äº†ï¼Œåœ¨Handlerä¸è¿›è¡Œæ¶ˆæ¯å¤„ç†ã€?/font>
Activity是一个UI¾U¿ç¨‹åQŒè¿è¡ŒäºŽä¸Èº¿½E‹ä¸åQŒAndroid¾pÈ»Ÿåœ¨å¯åŠ¨çš„æ—¶å€™ä¼šä¸ºActivity创å¾ä¸€ä¸ªæ¶ˆæ¯é˜Ÿåˆ—和消æ¯å¾ªçޝåQˆLooperåQ‰ã€‚详¾l†å®žçŽ°è¯·å‚考ActivityThread.javaæ–‡äšgã€?/font>
Handler的作用是把消æ¯åŠ å…¥ç‰¹å®šçš„åQˆLooperåQ‰æ¶ˆæ¯é˜Ÿåˆ—ä¸åQŒåƈ分å‘和处ç†è¯¥æ¶ˆæ¯é˜Ÿåˆ—ä¸çš„æ¶ˆæ¯ã€‚æž„é€ Handler的时候å¯ä»¥æŒ‡å®šä¸€ä¸ªLooper对象åQŒå¦‚æžœä¸æŒ‡å®šåˆ™åˆ©ç”¨å½“å‰çº¿½E‹çš„Looper创å¾ã€‚详¾l†å®žçŽ°è¯·å‚考Looperçš„æºç ã€?/font>
Activityã€Looperã€Handler的关¾pÕd¦‚下图所½Cºï¼š
一个Activityä¸å¯ä»¥åˆ›å»ºå¤šä¸ªå·¥ä½œçº¿½E‹æˆ–者其他的¾l„äšgåQŒå¦‚果这些线½E‹æˆ–è€…ç»„ä»¶æŠŠä»–ä»¬çš„æ¶ˆæ¯æ”¾å…¥Activity的主¾U¿ç¨‹æ¶ˆæ¯é˜Ÿåˆ—åQŒé‚£ä¹ˆè¯¥æ¶ˆæ¯ž®×ƒ¼šåœ¨ä¸»¾U¿ç¨‹ä¸å¤„ç†äº†ã€‚å› ä¸ÞZ¸»¾U¿ç¨‹ä¸€èˆ¬è´Ÿè´£ç•Œé¢çš„æ›´æ–°æ“作åQŒåƈ且Android¾pÈ»Ÿä¸çš„weget䏿˜¯¾U¿ç¨‹å®‰å…¨çš„,所以这¿Uæ–¹å¼å¯ä»¥å¾ˆå¥½çš„实现Androidç•Œé¢æ›´æ–°ã€‚在Android¾pÈ»Ÿä¸è¿™¿Uæ–¹å¼æœ‰ç€òq¿æ³›çš„è¿ç”¨ã€?/font>
那么å¦å¤–一个线½E‹æ€Žæ ·æŠŠæ¶ˆæ¯æ”¾å…¥ä¸»¾U¿ç¨‹çš„æ¶ˆæ¯é˜Ÿåˆ—å‘¢åQŸç”案是通过Handle对象åQŒåªè¦Handler对象以主¾U¿ç¨‹çš„Looper创å¾åQŒé‚£ä¹ˆè°ƒç”¨Handlerçš„sendMessage½{‰æŽ¥å£ï¼Œž®†ä¼šæŠŠæ¶ˆæ¯æ”¾å…¥é˜Ÿåˆ—都ž®†æ˜¯æ”‘Ö…¥ä¸Èº¿½E‹çš„æ¶ˆæ¯é˜Ÿåˆ—ã€‚åÆˆä¸”å°†ä¼šåœ¨Handlerä¸Èº¿½E‹ä¸è°ƒç”¨è¯¥handlerçš„handleMessageæŽ¥å£æ¥å¤„ç†æ¶ˆæ¯ã€?/font>
˜q™é‡Œé¢æ¶‰åŠåˆ°¾U¿ç¨‹åŒæ¥é—®é¢˜åQŒè¯·å…ˆå‚è€ƒå¦‚ä¸‹ä¾‹åæ¥ç†è§£Handler对象的线½E‹æ¨¡åž‹ï¼š
1ã€é¦–先创建MyHandler工程ã€?/font>
2ã€åœ¨MyHandler.javaä¸åŠ å…¥å¦‚ä¸‹çš„ä»£ç åQ?/font>
package com.simon; import android.app.Activity; import android.os.Bundle; import android.os.Message; import android.util.Log; import android.os.Handler; public class MyHandler extends Activity { static final String TAG = "Handler"; Handler h = new Handler(){ public void handleMessage (Message msg) { switch(msg.what) { case HANDLER_TEST: Log.d(TAG, "The handler thread id = " + Thread.currentThread().getId() + "\n"); break; } } }; static final int HANDLER_TEST = 1; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "The main thread id = " + Thread.currentThread().getId() + "\n"); new myThread().start(); setContentView(R.layout.main); } class myThread extends Thread { public void run() { Message msg = new Message(); msg.what = HANDLER_TEST; h.sendMessage(msg); Log.d(TAG, "The worker thread id = " + Thread.currentThread().getId() + "\n"); } } }
在这个例å䏿ˆ‘ä»¬ä¸»è¦æ˜¯æ‰“åŽÍ¼Œ˜q™ç§å¤„ç†æœºåˆ¶å„个模å—的所处的¾U¿ç¨‹æƒ…况。如下是我的机器˜q行¾l“æžœåQ?/font>
09-10 23:40:51.478: DEBUG/Handler(302): The main thread id = 1 09-10 23:40:51.569: DEBUG/Handler(302): The worker thread id = 8 09-10 23:40:52.128: DEBUG/Handler(302): The handler thread id = 1
我们å¯ä»¥çœ‹å‡ºæ¶ˆæ¯å¤„ç†æ˜¯åœ¨ä¸Èº¿½E‹ä¸å¤„ç†çš„,在消æ¯å¤„ç†å‡½æ•îC¸å¯ä»¥å®‰å…¨çš„调用主¾U¿ç¨‹ä¸çš„ä»ÖM½•资æºåQŒåŒ…括刷新界é¢ã€‚工作线½E‹å’Œä¸Èº¿½E‹è¿è¡Œåœ¨ä¸åŒçš„线½E‹ä¸åQŒæ‰€ä»¥å¿…™å»è¦æ³¨æ„˜q™ä¸¤ä¸ªçº¿½E‹é—´çš„竞争关¾p…R€?/font>
上例ä¸ï¼Œä½ å¯èƒ½æ³¨æ„到在工作线½E‹ä¸è®‰K—®äº†ä¸»¾U¿ç¨‹handler对象åQŒåƈ在调用handlerçš„å¯¹è±¡å‘æ¶ˆæ¯é˜Ÿåˆ—åŠ å…¥äº†ä¸€ä¸ªæ¶ˆæ¯ã€‚这个过½E‹ä¸ä¼šä¸ä¼šå‡ºçŽ°æ¶ˆæ¯é˜Ÿåˆ—æ•°æ®ä¸ä¸€è‡´é—®é¢˜å‘¢åQŸç”案是handler对象ä¸ä¼šå‡ºé—®é¢˜ï¼Œå› 䨓handler对象½Ž¡ç†çš„Looper对象是线½E‹å®‰å…¨çš„åQŒä¸½Ž¡æ˜¯åŠ å…¥æ¶ˆæ¯åˆ°æ¶ˆæ¯é˜Ÿåˆ—和从队列读出消æ¯éƒ½æ˜¯æœ‰åŒæ¥å¯¹è±¡ä¿æŠ¤çš„,具体请å‚考Looper.javaæ–‡äšgã€‚ä¸Šä¾‹ä¸æ²¡æœ‰ä¿®æ”¹handler对象åQŒæ‰€ä»¥handler对象ä¸å¯èƒ½ä¼šå‡ºçŽ°æ•°æ®ä¸ä¸€è‡´çš„问题ã€?/font>
通过上é¢çš„分æžï¼Œæˆ‘们å¯ä»¥å¾—出如下¾l“论åQ?/font>
1ã€å¦‚果通过工作¾U¿ç¨‹åˆäh–°ç•Œé¢åQŒæŽ¨èä‹É用handler对象æ¥å®žçްã€?/font>
2ã€æ³¨æ„工作线½E‹å’Œä¸Èº¿½E‹ä¹‹é—´çš„竞争关系。推èhandler对象在主¾U¿ç¨‹ä¸æž„é€ å®Œæˆï¼ˆòq¶ä¸”å¯åŠ¨å·¥ä½œ¾U¿ç¨‹ä¹‹åŽä¸è¦å†ä¿®æ”¹ä¹‹åQŒå¦åˆ™ä¼šå‡ºçŽ°æ•°æ®ä¸ä¸€è‡ß_¼‰åQŒç„¶åŽåœ¨å·¥ä½œ¾U¿ç¨‹ä¸å¯ä»¥æ”¾å¿ƒçš„调用å‘逿¶ˆæ¯SendMessage½{‰æŽ¥å£ã€?/font>
3ã€é™¤äº?所˜q°çš„hanlder对象之外的ä“Q何主¾U¿ç¨‹çš„æˆå‘˜å˜é‡å¦‚果在工作¾U¿ç¨‹ä¸è°ƒç”¨ï¼Œä»”细考虑¾U¿ç¨‹åŒæ¥é—®é¢˜ã€‚如果有必è¦éœ€è¦åŠ å…¥åŒæ¥å¯¹è±¡ä¿æŠ¤è¯¥å˜é‡ã€?/font>
4ã€handler对象的handleMessage接壞®†ä¼šåœ¨ä¸»¾U¿ç¨‹ä¸è°ƒç”¨ã€‚在˜q™ä¸ªå‡½æ•°å¯ä»¥æ”‘Ö¿ƒçš„调用主¾U¿ç¨‹ä¸ä“Q何å˜é‡å’Œå‡½æ•°åQŒè¿›è€Œå®Œæˆæ›´æ–°UIçš„ä“Q务ã€?/font>
5ã€Android很多API也利用Handler˜q™ç§¾U¿ç¨‹ç‰ÒŽ(gu¨©)€§ï¼Œä½œäؓ一¿U回调函数的å˜ç§åQŒæ¥é€šçŸ¥è°ƒç”¨è€…ã€‚è¿™æ ·Android框架ž®±å¯ä»¥åœ¨å…¶çº¿½E‹ä¸ž®†æ¶ˆæ¯å‘é€åˆ°è°ƒç”¨è€…çš„¾U¿ç¨‹æ¶ˆæ¯é˜Ÿåˆ—之ä¸åQŒä¸ç”¨æ‹…心线½E‹åŒæ¥çš„问题ã€?/font>
深入ç†è§£Android消æ¯å¤„ç†æœºåˆ¶å¯¹äºŽåº”用½E‹åºå¼€å‘éžå¸”R‡è¦ï¼Œä¹Ÿå¯ä»¥è®©ä½ 对¾U¿ç¨‹åŒæ¥æœ‰æ›´åŠ æ·±åˆÈš„认识。以上是最˜q‘Simonå¦ä¹ Android消æ¯å¤„ç†æœºåˆ¶çš„一点儿æ€È»“åQŒå¦‚有错误之处请ä¸å指教ã€?/font>
关键在于LOCAL_STATIC_JAVA_LIBRARIES := libarity和LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libarity:lily.jar
其实libarity是个åå—å¯ä»¥éšä¾¿å–ï¼Œä½†æ˜¯ä¸¤ä¸ªå±žæ€§çš„å€ÆD¦ä¸€æ ·å°±å¥½äº†åQŒä½†æ˜¯åŽé¢é‚£ä¸ªå†’å·é‡Œé¢å°±ä¸€å®šè¦å†™ä½ çš„jar包ååQŒä½ çš„jar包一定放在工½E‹çš„æ ¹ç›®å½•就好了åQŒç›®å½•结构如下:
-res
-src
-com
-ianc
-testjar
TestJar.java
android.mk
AndroidManifest.xml
default.properties
lily.jar