通州北大青鳥學(xué)術(shù)部推薦:對于Handler來說,它和與它調(diào)用它的Activity是出于同一線程的,下面進(jìn)行一下實驗
Java代碼
1. package org.hualang.handlertest3;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.os.Handler;
6. import android.util.Log;
7.
8. public class HandlerTest3 extends Activity {
9. private Handler handler = new Handler();
10. private String TAG = "System.out";
11. @Override
12. public void onCreate(Bundle savedInstanceState) {
13. super.onCreate(savedInstanceState);
14. handler.post(r);
15. setContentView(R.layout.main);
16. //Thread t = new Thread(r);
17. //t.start();
18.
19. Log.d(TAG,"Activity id:"+Thread.currentThread().getId());
20. Log.d(TAG,"Activity name:"+Thread.currentThread().getName());
21.
22. }
23. Runnable r = new Runnable()
24. {
25. public void run()
26. {
27. Log.d(TAG,"Handler id:"+Thread.currentThread().getId());
28. Log.d(TAG,"Handler name:"+Thread.currentThread().getName());
29. try {
30. Thread.sleep(5000);
31. } catch (InterruptedException e) {
32. // TODO Auto-generated catch block
33. e.printStackTrace();
34. }
35. }
36. };
37. }
運(yùn)行結(jié)果: (通州北大青鳥)
證明是同一個線程的兩個依據(jù):
①Activity的id或name和Handler的id或name是同樣的
②我設(shè)置了
handler.post(r);
setContentView(R.layout.main);
也就是,如果執(zhí)行后馬上顯示文本信息,那么可以證明它們不在同一個線程,但是實際情況是要先執(zhí)行了handler后5秒,才顯示文本信息,說明它們在同一線程
如果將代碼改為(通州北大青鳥)
Java代碼
1. //handler.post(r);
2. setContentView(R.layout.main);
3. Thread t = new Thread(r);
4. t.start();
再次執(zhí)行,運(yùn)行結(jié)果如下,通過start啟動線程,它們不在同一個線程中
Looper即循環(huán)的從隊列當(dāng)中取得消息的功能,如果在線程中使用Looper
那么,就會循環(huán)的從線程隊列當(dāng)中取得消息并處理,如果隊列當(dāng)中沒有消息的話
,線程就進(jìn)入了休眠狀態(tài)
Looper很少自己創(chuàng)建,在Android中給出了HandlerThread類,并且具有循環(huán)取得并處理消息的功能
下面來實現(xiàn)這種Activity和Handler分別在兩個線程中執(zhí)行,實現(xiàn)真正的異步處理
Java代碼 (通州北大青鳥)
1. package org.hualang.handlertest;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.os.Handler;
6. import android.os.HandlerThread;
7. import android.os.Looper;
8. import android.os.Message;
9. import android.util.Log;
10.
11. public class HandlerTest4 extends Activity {
12. /** Called when the activity is first created. */
13. @Override
14. public void onCreate(Bundle savedInstanceState) {
15. super.onCreate(savedInstanceState);
16. setContentView(R.layout.main);
17. Log.d("System.out","Activity所在線程的id:"+Thread.currentThread().getId());
18. /**
19. * 生成一個HandlerThread對象,實現(xiàn)了使用Looper來處理消息隊列的功能
20. * 這個類由Android應(yīng)用程序框架提供
21. */
22. HandlerThread handlerThread = new HandlerThread("handlerThread");
23. handlerThread.start();
24. MyHandler handler = new MyHandler(handlerThread.getLooper());
25. Message msg = handler.obtainMessage();
26. /**
27. * 將Message對象發(fā)送到目標(biāo)對象
28. * 所謂的目標(biāo)對象,就是生成該msg對象的handler對象
29. */
30. msg.sendToTarget();
31. }
32. class MyHandler extends Handler
33. {
34. public MyHandler()
35. {
36. }
37. public MyHandler(Looper looper)
38. {
39. super(looper);
40. }
41. public void handleMessage(Message msg)
42. {
43. Log.d("System.out", "handler所在線程的id:"+Thread.currentThread().getId());
44. }
45. }
46. }
運(yùn)行結(jié)果:
可以看到,Activity和Handler是在兩個不同的線程中執(zhí)行的,這樣就是實現(xiàn)了真正的異步處理(通州北大青鳥)
1、首先創(chuàng)建一個HandlerThread對象,這個HandlerThread類實現(xiàn)了循環(huán)的取得消息并處理
2、用start方法啟動一個新線程
3、創(chuàng)建MyHandler類,里面?zhèn)鬟f的參數(shù)即Looper方法所獲得的可以循環(huán)在隊列中取得的消息
4、MyHandler類調(diào)用的是帶參數(shù)Looper的構(gòu)造方法,并且實現(xiàn)了handlerMessage方法
5、獲取一個Message對象
6、將這個對象發(fā)送到生成該msg對象的handler對象,從而執(zhí)行了handleMessage方法
-----------------------------------------------------------------------------------------------------
最后,將說一下Message里傳送的數(shù)據(jù)的使用,這里的msg對象可以使用arg1,arg2或者obj
arg1 and arg2 are lower-cost alternatives to using setData() if you only need to store a few integer values. 也就是相對于setData()方法,如果你僅僅保存一些簡單的整形數(shù)的話,arg1,arg2對資源的要求較低,而setData()方法一般用于傳遞大量數(shù)據(jù)的時候會用到
如果是msg.obj,那么可以這樣用
msg.obj = "Welcome to china";
然后在handleMessage()方法中用
String str = (String)msg.obj;來獲得傳遞的值
如果使用getData()方法的話,需要用到Bundle對象來傳遞,下面用個例子來說明
Java代碼
1. Bundle b = new Bundle();
2. b.putInt("age", 22);
3. b.putString("name", "loulijun");
4. msg.setData(b);
5. msg.sendToTarget();
上面的代碼用來設(shè)置要傳遞的數(shù)據(jù)(通州北大青鳥)
下面的代碼用來獲取Bundle傳遞過來的數(shù)據(jù)并且用Toast來顯示
Java代碼
1. Bundle b = msg.getData();
2. int age = b.getInt("age");
3. String name = b.getString("name");
4. Toast toast = Toast.makeText(getApplicationContext(), "age="+age+"name="+name, Toast.LENGTH_LONG);
5. toast.show();
package org.hualang.handlertest;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
public class HandlerTest4 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("System.out","Activity所在線程的id:"+Thread.currentThread().getId());
/**
* 生成一個HandlerThread對象,實現(xiàn)了使用Looper來處理消息隊列的功能
* 這個類由Android應(yīng)用程序框架提供
*/
HandlerThread handlerThread = new HandlerThread("handlerThread");
/**
* 使用HandlerThread的getLooper()方法之前,必須先調(diào)用該類的start()方法,否則是個null,會報錯
*/
handlerThread.start();
MyHandler handler = new MyHandler(handlerThread.getLooper());
Message msg = handler.obtainMessage();
/**
* 將Message對象發(fā)送到目標(biāo)對象
* 所謂的目標(biāo)對象,就是生成該msg對象的handler對象
*/
//msg.obj = "Hello world";
Bundle b = new Bundle();
b.putInt("age", 22);
b.putString("name", "loulijun");
msg.setData(b);
msg.sendToTarget();
}
class MyHandler extends Handler
{
public MyHandler()
{
}
public MyHandler(Looper looper)
{
super(looper);
}
public void handleMessage(Message msg)
{
//String str = (String)msg.obj
Bundle b = msg.getData();
int age = b.getInt("age");
String name = b.getString("name");
Toast toast = Toast.makeText(getApplicationContext(), "age="+age+"name="+name, Toast.LENGTH_LONG);
toast.show();
Log.d("System.out", "handler所在線程的id:"+Thread.currentThread().getId());
}
}
}
運(yùn)行結(jié)果:(通州北大青鳥)
(通州北大青鳥)