❶ android在子線程用handler發送的消息,主線程是怎麼loop到的
因為你是在主線程創建的handler實例,比如你是這樣實例化handler
然後調用looper.loop();就開始了消息循環。這就是為什麼在主線程發消息住線程還能收到消息的原因。因為發送消息的實例是在主線程實例化的就有了主線程的looper。
❷ android looper 怎麼理解
Android
中
Looper
和
handler
的聯系及處理
最近一直在看
Android
內核的代碼。把
Looper
及
Handler
這一節先分享一下:
Handle
主要起一個代理中介的作用,具體對象要向底層發請求,得通過
Handler
,
Handler
把這個請求放進對應的
MessageQueue
(消息隊列)中,而
MessageQueue
是由
Looper
來維護的。
Looper
中有一個循環,循環讀取
MessageQueue
中的請求,發給相應的底層處理(這個過程有點復雜)。當底層
有信息返回時,
也會先放進
MessageQueue
中,
然後對應的
Looper
遍歷,
交給對
應的
Handler
處理。
Handler
找出對應的回調函數或其他已注冊的相關方法,讓
其進行處理,最終在界面有一個反應。
以下是我寫的一個
demo
,
主要是如何關聯
Looper
、
Handler
、
以及對應的線程
(
MessageQueue
是
Looper
的一個成員)。
1.
測試方法入口:
testLooper1.java
package com.linquan.test.loop1;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class testLooper1 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(MyConstant.TAG, "main start...");
new MyThread().start();
Message msg = new Message();
msg.what = MyConstant.CONSTANT3;
while(MyThread.h == null){
Log.d(MyConstant.TAG, "handler is not init ! please wait a
monment....");
try {
Thread.sleep(300);//
由於這里是測試,
所以加上此行代碼,
避免出錯。
實
際中多為用戶觸發事件,此時
handle
應該已經初始化了。
} catch (InterruptedException e) {
e.printStackTrace();
❸ looper的作用 android 為什麼要循環
給你舉個例子:
用handler傳遞消息時候。你先sendmessage。這時候消息到looper然後你再looper當中更具msg.what獲取相應的消息。looper相當於一個消息收取中介。所以要有循環。我自己的理解。
❹ android的looper類 Looper中有許多都是靜態方法或者靜態屬性,一個應用程序
你好 ,n個應用的話對應 >=n 個進程,一個應用可以有多個進程。
一個線程對應一個looper,ui主線程系默認有一個,非主線程可以調用prepare方法獲得一個looper
❺ android中looper的實現原理,為什麼調用looper.prepare就在當前線程關聯了一個lo
實際上:消息發送和計劃任務提交之後,它們都會進入某線程的消息隊列中,我們可以把這個線程稱之為目標線程。不論是主線程還是子線程都可以成為目標線程。上例中之所以在主線程中處理消息,是因為我們要更新UI,按照android中的規定我們必須由主線程更新UI。所以我們讓主線程成為了目標線程。
那麼如何控制讓某個線程成為目標線程呢?
這就引出了Looper的概念。Android系統中實現了消息循環機制,Android的消息循環是針對線程的,每個線程都可以有自己的消息隊列和消息循環。Android系統中的通過Looper幫助線程維護著一個消息隊列和消息循環。通過Looper.myLooper()得到當前線程的Looper對象,通過Looper.getMainLooper()得到當前進程的主線程的Looper對象。
前面提到每個線程都可以有自己的消息隊列和消息循環,然而我們自己創建的線程默認是沒有消息隊列和消息循環的(及Looper),要想讓一個線程具有消息處理機制我們應該在線程中先調用Looper.prepare()來創建一個Looper對象,然後調用Looper.loop()進入消息循環。如上面的源碼所示。
當我們用Handler的構造方法創建Handler對象時,指定handler對象與哪個具有消息處理機制的線程(具有Looper的線程)相關聯,這個線程就成了目標線程,可以接受消息和計劃任務了。Handler中的構造方法如下:
[java] view
plainprint?
public Handler() {
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 = null;
}
public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = null;
}
public Handler() {
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 = null;
}
public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = null;
}
在上述的計時器的例子中,之所以可以在主線程中處理消息而我們自己並沒有調用Looper.prepare()等方法,是因為Android系統在Activity啟動時為其創建一個消息隊列和消息循環,當我們用無參的Handler構造方法創建對象時又用了當前線程的Looper對象,及將handler與主線程中的Looper對象進行了關聯。
android中是使用Looper機制來完成消息循環的,但每次創建線程時都先初始化Looper比較麻煩,因此Android為我們提供了一個HandlerThread類,他封裝了Looper對象,是我們不用關心Looper的開啟和釋放問題。
不管是主線程還是其他線程只要有Looper的線程,別的線程就可以向這個線程的消息隊列中發送消息和任務。
我們使用HandlerThread類代替上一篇文章中的子線程,並用HandlerThread類中的Looper對象構造Handler,則接受消息的目標線程就不是主線程了,而是HandlerThread線程。代碼如下:
[java] view
plainprint?
public class clockActivity extends Activity {
/** Called when the activity is first created. */
private String TAG="clockActivity";
private Button endButton;
private TextView textView;
private int timer=0;
private boolean isRunning=true;
private Handler handler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
endButton=(Button)findViewById(R.id.endBtn);
textView=(TextView)findViewById(R.id.textview);
endButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
isRunning=false;
}
});
HandlerThread thread=new HandlerThread("myThread");
handler=new Handler(thread.getLooper());//與HandlerThread中的Looper對象關聯
thread.start();
Runnable r=new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
if(isRunning){
textView.setText("走了"+timer+"秒");
timer++;
handler.postDelayed(this, 1000);//提交任務r,延時1秒執行
}
}
};
handler.postDelayed(r, 1000);
}
}
public class clockActivity extends Activity {
/** Called when the activity is first created. */
private String TAG="clockActivity";
private Button endButton;
private TextView textView;
private int timer=0;
private boolean isRunning=true;
private Handler handler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
endButton=(Button)findViewById(R.id.endBtn);
textView=(TextView)findViewById(R.id.textview);
endButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
isRunning=false;
}
});
HandlerThread thread=new HandlerThread("myThread");
handler=new Handler(thread.getLooper());//與HandlerThread中的Looper對象關聯
thread.start();
Runnable r=new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
if(isRunning){
textView.setText("走了"+timer+"秒");
timer++;
handler.postDelayed(this, 1000);//提交任務r,延時1秒執行
}
}
};
handler.postDelayed(r, 1000);
}
}
此時處理任務會在handlerThread線程中完成。當然這個例子會出線異常:依然是因為在非主線程中更新了UI。這樣做只是為了大家能夠理解這種機制。
深入理解Android消息處理機制對於應用程序開發非常重要,也可以讓我們對線程同步有更加深刻的認識,希望這篇文章可以對朋友們有所幫助。
❻ Android Looper 主線程的Looper.looper()是在哪調用的
http://blog.csdn.net/hello_12413/article/details/51759787
這個可以參考下,