Android handler
来源:互联网 发布:ubuntu删除文件夹 编辑:程序博客网 时间:2024/06/16 16:11
1:不要在主线程中执行耗时操作,
因为主线程是用来画界面的,每15ms一个。然后接收用户的触摸。
如果我们在主线程执行一个耗时操作的话,它就会卡在那里了。
图片下载的->线程——handler
如果是联网的API接口-》异步任务
谁有handler 谁就能接受消息。谁有handler,谁就可以接受消息,
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
主线程就是用来画UI的。
子线程不允许更新UI界面上面的内容的,请看第5个实例
handler 创建的时候就是被绑定到了创建它的线程
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
2:“应用程序无响应”是否等待或删除?就是在主线程中执行了太多的
3:handle
//按钮的点击事件的处理,是在主线程执行的
//当主线程被耗时操作占用了之后,将不能处理其他的输入了。
//也就是点击其他的按钮没有反应了
执行两个button:
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="处理操作"
android:onClick="btnForWork"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="点击试试"
android:onClick="btnClickMe"
/>
点击的方法:
/**
* 点击事件执行耗时操作
* @param view
*/
public void btnForWork(View view) {
//按钮的点击事件的处理,是在主线程执行的
//当主线程被耗时操作占用了之后,将不能处理其他的输入了。
//也就是点击其他的按钮没有反应了
for(int i=0;i<10000;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void btnClickMe(View view) {
Toast.makeText(this,"点到我了",Toast.LENGTH_LONG).show();
}
4:更新:
public class MyActivity extends Activity implements Runnable{
public void btnForWork(View view) {
//按钮的点击事件的处理,是在主线程执行的
//当主线程被耗时操作占用了之后,将不能处理其他的输入了。
//也就是点击其他的按钮没有反应了
// for(int i=0;i<10000;i++){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
Thread thread = new Thread(this);
thread.start();
}
public void run(){
for(int i=0;i<10000;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5:报错的实例:添加一行txtState.setText("计数完成");会报错,因为子线程不能功能心UI
public void run(){
for(int i=0;i<10000;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
txtState.setText("计数完成");
}
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6740)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:962)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.widget.TextView.checkForRelayout(TextView.java:7707)
at android.widget.TextView.setText(TextView.java:4447)
at android.widget.TextView.setText(TextView.java:4284)
at android.widget.TextView.setText(TextView.java:4259)
at com.zqxue.HandlerDemoLesson.MyActivity.run(MyActivity.java:52)
at java.lang.Thread.run(Thread.java:841)
6:完成的时候,需要告诉主线程更新UI。
Socket。
ServerSocket 就是不停的等待接受消息
Socket 就是发消息的。
引入Handler
主线中有一个Hnalder对象
子线程
7:
Handler 用于线程之间的消息传递,一个线程A创建了Handler之后
将这个Handler交给另一个线程线程B,当线程B通过handler 发送消息的时候,
线程A,能够自动的获取到这个消息。当线程A 收到消息,就可以利用Handler的方法来处理消息。
+++++++++++++++++++++++++++++++++++++
反过来是不行的,
谁有Handler,谁就能收消息,
上面的B 可以给A 发消息,但是A不能给B发消息。
//TODO:更新UI的操作只能够在子线程完成
//如果需要从子线程,告诉子线程更新UI,子线程需要给主线程发消息。
//主线程需要Handler,才可以从其它线程收到消息。
/**
* 关于主线程
* 1.所有的Activity 都是在主线程创建的
* 2:Activity的所有的生命周期方法,都是在主线程调用的
* 3:Activity 所有成员变量的声明初始化都是在主线程调用的
*/
++++++++++++++++++++++++++++++++++++++++++
//用于接收从子线程发送过来的消息
//根据官方的说明,Hanlder创建的时候,在那个线程创建,就被绑定到那个线程
//当亲啊的这个handler,被绑定到了主线程上
//其他线程,就可以通过这个Handler 来给主线程发送消息。
private Handler handler = new Handler(){
/**
* 当子线程使用Hanlder发送消息之后,handler所属的线程就会收到这个消息
* 收到这个消息之后,就会交给handler自身来处理,
* 使用handlerMessage 来执行这个消息的操作
* !!!这个方法在绑定的线程中--自动--执行,当前绑定在主线程,所以就会在主线程中自动执行
* @param msg 子线程发送的消息
*/
@Override
public void handleMessage(Message msg) {
//删除掉super
//super.handleMessage(msg);
}
};
++++++++++++++++++++++++++++++++++++++++++++
public void handleMessage(Message msg) {
//删除掉super
//super.handleMessage(msg);
//msg.what 消息的识别码,可以任意设置,根据数值进行不同处理,用户定义的消息码,是自己要定义的,可以是998 199,
// msg.arg1 相对于setData()消耗的小,就像邮递,一个小的组件,没有必要弄一个大的包裹,setData()需要用到bundler,所以直接使用arg1,arg2
// msg.arg2 简单的数字表示的数值,需要更具自己的业务场景来定义,就像当前网络,
// msg.obj 可以是任意对象,是从另一个线程发送过来的。可以代表是数据
//msg.getData();Bundler对象,用于传递Android 标准的数据对象,是和Messager配合更好
}
++++++++++++++++++++++++++++++++++++++++++++
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
//1.定义what,代表不同的额消息,更具what 来进行不同的处理;
int what = msg.what;
switch(what){
case WHAT_UPDATE_STATE:
//对于本例,定义msg.obj 代表状态字符串,
String str =(String) msg.obj;
txtState.setText(str);
break;
}
}
++++++++++++++++++++++++++++++++++++++++++++
run 方法里面添加:
Message msg = new Message();
msg.what=WHAT_UPDATE_STATE;
msg.obj="计数完成";
handler.sendMessage(msg);
++++++++++++++++++++++++++++++++++++++++++++
现在在run 方法的循环里面将当前的i传handler
先
public static final int WHAT_UPDATE_NUMBER = 2;
然后修改
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
int what = msg.what;
switch(what){
case WHAT_UPDATE_STATE:
//对于本例,定义msg.obj 代表状态字符串,
String str =(String) msg.obj;
txtState.setText(str);
break;
case WHAT_UPDATE_NUMBER:
txtState.setText(String.valueOf(msg.arg1));
break;
}
}
};
跟新run:
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = new Message();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
}
Message msg = new Message();
msg.what=WHAT_UPDATE_STATE;
msg.obj="计数完成";
handler.sendMessage(msg);
}
++++++++++++++++++++++++++++++++++++++++++++++++++++
Message 的创建都和设置
1:Message 构造(不要再循环中使用)
2:Message.obtainMessage()方法,利用已经有的Message进行复用;
++++++++++++++++++++++++++++++++++++++++++++++++++++
更新run方法里面的
Message msg = new Message();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
更新为:
//重用之前创建过的消息,如果没有自动创建新的。
Message msg = Message.obtain();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
++++++++++++++++++++++++++++++
obtain()方法的策略,当一个Message 被处理完之后,才嫩够复用,如果obtain 执行的时候,有可以被复用的Message
那么直接使用,
如果所有Message没有执行完,这个时候obtain()调用,那么不会找到复用的消息,因此就会创建新的Message;
++++++++++++++++++++++++++++++
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Message msg = new Message();
//重用之前创建过的消息,如果没有自动创建新的。
Message msg = Message.obtain();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Message msg = new Message();
Message msg =Message.obtain();
msg.what=WHAT_UPDATE_STATE;
msg.obj="计数完成";
handler.sendMessage(msg);
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Handler 发送消息的步骤
Hadler sendMessage(Message)将消息发送到内部的消息队列中
MessageQuere mQueue handler 的成员变量mQueue 实际上就是构造时候Looper内部的消息队列。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Looper 传送带的形式 水车,,,
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
android 的main 方法在activity-》activityThread 里面的main
关系图:
可以把MessageQueue 看作是adapter,Message 是里面的data
MessageQueue 使用跟着adapter,handler 去更新这个adapter。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
说白了就是对象间的引用
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
关系描述:
1:现在成在启动的时候,准备一个Looper,这个Looper就会自动和线程链接在一起;
2:Handler在创建的时候,会自动的查找当前线程的Looper对象,进行消息队列的获取
3:Looper通过Loop()方法,在当前线程进行一个死循环,一直来检测消息队列,获取消息;有点像ServerSocket 一个while true的循环
4:在子线程中,获取handler 对象;进行消息的发送,发送的时候就会将这个消息,发送给Looper
所包含的消息队列中;
5:第三点Looper.loop()内部因为一直等待消息,当发送的消息添加到队列的时候,loop的方法就可以检测到
就可以进行处理,调用message中对应的handler的方法来进行处理;因为处理的步骤是在loop方法中执行的
也就代表handler的handlerMessage执行是在Looper 所在的线程中执行的。
如果Looper在主线程,Handler 也在主次按成创建,代表,handlerMessage就在主线程执行的。
+++++++++++++++++++++++++++++++++++++++++++
自己做一个聊天的
++++++++++++++++++++++++++++++++++++++++++++
新建一个activity 继承Runnable
//子线程的Handler
private Handler subHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.char_activity);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
//创建Looper 对象,绑定到当前的线程
Looper.prepare();
subHandler =new Handler();
Looper.loop();
}
如果,下面会报错,因为handler 必须要绑定Looper
public void run() {
//创建Looper 对象,绑定到当前的线程
//Looper.prepare();
subHandler =new Handler();
//Looper.loop();
}
子线程Looper的退出,可以调用Looper的成员方法叫做quit()或者quitSafely()
Looper.myLooper().quit 代表当前线程中的Looper 就退出了,looper的loop方法,结束;
Looper looper = Looper.myLooper();//获取当亲啊的Looper
looper.quitSafely();
注意:主线程不允许退出;
<ListView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
></ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="btnSendMessage"
android:text="创建消息"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="btnEndLooper"
android:text="退出子线程"
/>
</LinearLayout>
public class CharActivity extends Activity implements Runnable {
//子线程的Handler
private Handler subHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.char_activity);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
//创建Looper 对象,绑定到当前的线程
Looper.prepare();
subHandler =new Handler(){
@Override
public void handleMessage(Message msg) {
int what = msg.what;
switch (what) {
case 9:
Log.d("Chat", "收到消息");
break;
case 10:
Looper looper = Looper.myLooper();//获取当亲啊的Looper
looper.quitSafely();
break;
}
}
};
Looper.loop();//一直等待消息
}
/**
* 点击按钮,发送消息,调用子线程的Handler发送消息
*/
public void btnSendMessage(View view){
Message message = subHandler.obtainMessage(9);
subHandler.sendMessage(message);
}
/**
* 点击按钮,退出子线程的Looper
* @param view
*/
public void btnEndLooper(View view) {
Message message = subHandler.obtainMessage(10);
subHandler.sendMessage(message);
}
}
1:关于主线程Looper的创建,在所有的Activity 启动之前 实际上主线程的Looper已经由系统创建好了,并且也执行了Looper的loop方法
2:在主线程中,不需要再进行Looper.prepare();
3:所有的Acitivity 都是。。。。。
Looper的方法:
1:Looper.prepare() 给当前线程创建并且绑定一个Looper对象;
2:Looper.myLooper():获取当前线程的Looper对象,
3:Looper.loop()当前线程阻塞,一直等待消息;
4:ThreadLocal
点击发送:把输入宽内容发送给子线程,子线程使用handler处理消息,内部调用服务器API,发送网络请求
因为主线程是用来画界面的,每15ms一个。然后接收用户的触摸。
如果我们在主线程执行一个耗时操作的话,它就会卡在那里了。
图片下载的->线程——handler
如果是联网的API接口-》异步任务
谁有handler 谁就能接受消息。谁有handler,谁就可以接受消息,
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
主线程就是用来画UI的。
子线程不允许更新UI界面上面的内容的,请看第5个实例
handler 创建的时候就是被绑定到了创建它的线程
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
2:“应用程序无响应”是否等待或删除?就是在主线程中执行了太多的
3:handle
//按钮的点击事件的处理,是在主线程执行的
//当主线程被耗时操作占用了之后,将不能处理其他的输入了。
//也就是点击其他的按钮没有反应了
执行两个button:
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="处理操作"
android:onClick="btnForWork"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="点击试试"
android:onClick="btnClickMe"
/>
点击的方法:
/**
* 点击事件执行耗时操作
* @param view
*/
public void btnForWork(View view) {
//按钮的点击事件的处理,是在主线程执行的
//当主线程被耗时操作占用了之后,将不能处理其他的输入了。
//也就是点击其他的按钮没有反应了
for(int i=0;i<10000;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void btnClickMe(View view) {
Toast.makeText(this,"点到我了",Toast.LENGTH_LONG).show();
}
4:更新:
public class MyActivity extends Activity implements Runnable{
public void btnForWork(View view) {
//按钮的点击事件的处理,是在主线程执行的
//当主线程被耗时操作占用了之后,将不能处理其他的输入了。
//也就是点击其他的按钮没有反应了
// for(int i=0;i<10000;i++){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
Thread thread = new Thread(this);
thread.start();
}
public void run(){
for(int i=0;i<10000;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5:报错的实例:添加一行txtState.setText("计数完成");会报错,因为子线程不能功能心UI
public void run(){
for(int i=0;i<10000;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
txtState.setText("计数完成");
}
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6740)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:962)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.view.View.requestLayout(View.java:16784)
at android.widget.TextView.checkForRelayout(TextView.java:7707)
at android.widget.TextView.setText(TextView.java:4447)
at android.widget.TextView.setText(TextView.java:4284)
at android.widget.TextView.setText(TextView.java:4259)
at com.zqxue.HandlerDemoLesson.MyActivity.run(MyActivity.java:52)
at java.lang.Thread.run(Thread.java:841)
6:完成的时候,需要告诉主线程更新UI。
Socket。
ServerSocket 就是不停的等待接受消息
Socket 就是发消息的。
引入Handler
主线中有一个Hnalder对象
子线程
7:
Handler 用于线程之间的消息传递,一个线程A创建了Handler之后
将这个Handler交给另一个线程线程B,当线程B通过handler 发送消息的时候,
线程A,能够自动的获取到这个消息。当线程A 收到消息,就可以利用Handler的方法来处理消息。
+++++++++++++++++++++++++++++++++++++
反过来是不行的,
谁有Handler,谁就能收消息,
上面的B 可以给A 发消息,但是A不能给B发消息。
//TODO:更新UI的操作只能够在子线程完成
//如果需要从子线程,告诉子线程更新UI,子线程需要给主线程发消息。
//主线程需要Handler,才可以从其它线程收到消息。
/**
* 关于主线程
* 1.所有的Activity 都是在主线程创建的
* 2:Activity的所有的生命周期方法,都是在主线程调用的
* 3:Activity 所有成员变量的声明初始化都是在主线程调用的
*/
++++++++++++++++++++++++++++++++++++++++++
//用于接收从子线程发送过来的消息
//根据官方的说明,Hanlder创建的时候,在那个线程创建,就被绑定到那个线程
//当亲啊的这个handler,被绑定到了主线程上
//其他线程,就可以通过这个Handler 来给主线程发送消息。
private Handler handler = new Handler(){
/**
* 当子线程使用Hanlder发送消息之后,handler所属的线程就会收到这个消息
* 收到这个消息之后,就会交给handler自身来处理,
* 使用handlerMessage 来执行这个消息的操作
* !!!这个方法在绑定的线程中--自动--执行,当前绑定在主线程,所以就会在主线程中自动执行
* @param msg 子线程发送的消息
*/
@Override
public void handleMessage(Message msg) {
//删除掉super
//super.handleMessage(msg);
}
};
++++++++++++++++++++++++++++++++++++++++++++
public void handleMessage(Message msg) {
//删除掉super
//super.handleMessage(msg);
//msg.what 消息的识别码,可以任意设置,根据数值进行不同处理,用户定义的消息码,是自己要定义的,可以是998 199,
// msg.arg1 相对于setData()消耗的小,就像邮递,一个小的组件,没有必要弄一个大的包裹,setData()需要用到bundler,所以直接使用arg1,arg2
// msg.arg2 简单的数字表示的数值,需要更具自己的业务场景来定义,就像当前网络,
// msg.obj 可以是任意对象,是从另一个线程发送过来的。可以代表是数据
//msg.getData();Bundler对象,用于传递Android 标准的数据对象,是和Messager配合更好
}
++++++++++++++++++++++++++++++++++++++++++++
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
//1.定义what,代表不同的额消息,更具what 来进行不同的处理;
int what = msg.what;
switch(what){
case WHAT_UPDATE_STATE:
//对于本例,定义msg.obj 代表状态字符串,
String str =(String) msg.obj;
txtState.setText(str);
break;
}
}
++++++++++++++++++++++++++++++++++++++++++++
run 方法里面添加:
Message msg = new Message();
msg.what=WHAT_UPDATE_STATE;
msg.obj="计数完成";
handler.sendMessage(msg);
++++++++++++++++++++++++++++++++++++++++++++
现在在run 方法的循环里面将当前的i传handler
先
public static final int WHAT_UPDATE_NUMBER = 2;
然后修改
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
int what = msg.what;
switch(what){
case WHAT_UPDATE_STATE:
//对于本例,定义msg.obj 代表状态字符串,
String str =(String) msg.obj;
txtState.setText(str);
break;
case WHAT_UPDATE_NUMBER:
txtState.setText(String.valueOf(msg.arg1));
break;
}
}
};
跟新run:
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = new Message();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
}
Message msg = new Message();
msg.what=WHAT_UPDATE_STATE;
msg.obj="计数完成";
handler.sendMessage(msg);
}
++++++++++++++++++++++++++++++++++++++++++++++++++++
Message 的创建都和设置
1:Message 构造(不要再循环中使用)
2:Message.obtainMessage()方法,利用已经有的Message进行复用;
++++++++++++++++++++++++++++++++++++++++++++++++++++
更新run方法里面的
Message msg = new Message();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
更新为:
//重用之前创建过的消息,如果没有自动创建新的。
Message msg = Message.obtain();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
++++++++++++++++++++++++++++++
obtain()方法的策略,当一个Message 被处理完之后,才嫩够复用,如果obtain 执行的时候,有可以被复用的Message
那么直接使用,
如果所有Message没有执行完,这个时候obtain()调用,那么不会找到复用的消息,因此就会创建新的Message;
++++++++++++++++++++++++++++++
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Message msg = new Message();
//重用之前创建过的消息,如果没有自动创建新的。
Message msg = Message.obtain();
msg.what=WHAT_UPDATE_NUMBER;
msg.arg1=i;
handler.sendMessage(msg);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Message msg = new Message();
Message msg =Message.obtain();
msg.what=WHAT_UPDATE_STATE;
msg.obj="计数完成";
handler.sendMessage(msg);
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Handler 发送消息的步骤
Hadler sendMessage(Message)将消息发送到内部的消息队列中
MessageQuere mQueue handler 的成员变量mQueue 实际上就是构造时候Looper内部的消息队列。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Looper 传送带的形式 水车,,,
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
android 的main 方法在activity-》activityThread 里面的main
关系图:
可以把MessageQueue 看作是adapter,Message 是里面的data
MessageQueue 使用跟着adapter,handler 去更新这个adapter。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
说白了就是对象间的引用
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
关系描述:
1:现在成在启动的时候,准备一个Looper,这个Looper就会自动和线程链接在一起;
2:Handler在创建的时候,会自动的查找当前线程的Looper对象,进行消息队列的获取
3:Looper通过Loop()方法,在当前线程进行一个死循环,一直来检测消息队列,获取消息;有点像ServerSocket 一个while true的循环
4:在子线程中,获取handler 对象;进行消息的发送,发送的时候就会将这个消息,发送给Looper
所包含的消息队列中;
5:第三点Looper.loop()内部因为一直等待消息,当发送的消息添加到队列的时候,loop的方法就可以检测到
就可以进行处理,调用message中对应的handler的方法来进行处理;因为处理的步骤是在loop方法中执行的
也就代表handler的handlerMessage执行是在Looper 所在的线程中执行的。
如果Looper在主线程,Handler 也在主次按成创建,代表,handlerMessage就在主线程执行的。
+++++++++++++++++++++++++++++++++++++++++++
自己做一个聊天的
++++++++++++++++++++++++++++++++++++++++++++
新建一个activity 继承Runnable
//子线程的Handler
private Handler subHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.char_activity);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
//创建Looper 对象,绑定到当前的线程
Looper.prepare();
subHandler =new Handler();
Looper.loop();
}
如果,下面会报错,因为handler 必须要绑定Looper
public void run() {
//创建Looper 对象,绑定到当前的线程
//Looper.prepare();
subHandler =new Handler();
//Looper.loop();
}
子线程Looper的退出,可以调用Looper的成员方法叫做quit()或者quitSafely()
Looper.myLooper().quit 代表当前线程中的Looper 就退出了,looper的loop方法,结束;
Looper looper = Looper.myLooper();//获取当亲啊的Looper
looper.quitSafely();
注意:主线程不允许退出;
<ListView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
></ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="btnSendMessage"
android:text="创建消息"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="btnEndLooper"
android:text="退出子线程"
/>
</LinearLayout>
public class CharActivity extends Activity implements Runnable {
//子线程的Handler
private Handler subHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.char_activity);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
//创建Looper 对象,绑定到当前的线程
Looper.prepare();
subHandler =new Handler(){
@Override
public void handleMessage(Message msg) {
int what = msg.what;
switch (what) {
case 9:
Log.d("Chat", "收到消息");
break;
case 10:
Looper looper = Looper.myLooper();//获取当亲啊的Looper
looper.quitSafely();
break;
}
}
};
Looper.loop();//一直等待消息
}
/**
* 点击按钮,发送消息,调用子线程的Handler发送消息
*/
public void btnSendMessage(View view){
Message message = subHandler.obtainMessage(9);
subHandler.sendMessage(message);
}
/**
* 点击按钮,退出子线程的Looper
* @param view
*/
public void btnEndLooper(View view) {
Message message = subHandler.obtainMessage(10);
subHandler.sendMessage(message);
}
}
1:关于主线程Looper的创建,在所有的Activity 启动之前 实际上主线程的Looper已经由系统创建好了,并且也执行了Looper的loop方法
2:在主线程中,不需要再进行Looper.prepare();
3:所有的Acitivity 都是。。。。。
Looper的方法:
1:Looper.prepare() 给当前线程创建并且绑定一个Looper对象;
2:Looper.myLooper():获取当前线程的Looper对象,
3:Looper.loop()当前线程阻塞,一直等待消息;
4:ThreadLocal
点击发送:把输入宽内容发送给子线程,子线程使用handler处理消息,内部调用服务器API,发送网络请求
0 0
- android Handler
- android Handler
- android Handler
- android Handler
- Android Handler
- android---handler
- android-handler
- Android Handler
- Android Handler
- Android Handler
- android Handler
- android--Handler
- Android Handler
- Android Handler
- Android Handler
- Android Handler
- Android handler
- Android Handler
- 电商网站的初期技术选型
- [菜鸟初学nodejs系列] 安装socket.io库
- How to read/write files within a Linux kernel module?
- LightOJ1074 Extended Traffic (SPFA+DFS)
- mysql如何防止插入重复数据?
- Android handler
- Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI
- 结构体比较
- MongoDB Sql语法
- 计算机中数据的表示存储和处理
- 伺服驱动器动力电和控制电
- 数据结构与算法的理解
- jquery字符串&Json互转
- java.lang.UnsupportedOperationException