Android(安卓)Handler学习之异步与多线程(★推荐)
文章来源:http://blog.csdn.net/wyzxk888/article/details/6968848
推荐文章:http://blog.csdn.net/yegongheng/article/details/38845953
花了若干天反复的学习了一下Handler,但是还是留下了许多问题,可能是自己太笨了,这里也自己留两份笔记方便以后回头看。
Handler注意点1:在哪个线程创建的Handler,Handler就属于哪个线程。
Handler注意点2:Handler调用Post(Runnable)函数时,不会启动另外一个线程,就是当前线程。
这个在做UI更新中要特别注意,这也是很多人问为什么调用了post方法UI线程还是阻塞了的原因,因为这样只是用Handler实现了异步,没有多线程。
Handler注意点3:在子线程中默认是没有MessageQueue的。
解决方法:用主线程的Handler发送消息到主线程的MessageQueue。
子线程创建Handler,获取主线程的MessageQueue,即获得主线程的Looper,(方法new Handler(Loop.getMainLooper()))
单纯异步与多线程异步证明:
XML布局:
[html] view plain copy- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <Button
- android:id="@+id/button1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="handlertest1"/>
- <Button
- android:id="@+id/button2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="handlertest2"/>
- <Button
- android:id="@+id/button3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="handlertest3"/>
- <Button
- android:id="@+id/button4"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="handlertest4"/>
- <ProgressBar
- android:id="@+id/progressBar1"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- <TextView
- android:id="@+id/textView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="whichtest?:"
- android:textAppearance="?android:attr/textAppearanceLarge"/>
- </LinearLayout>
Java Code:
[java] view plain copy- packagenet.john;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.os.Handler;
- importandroid.os.Message;
- importandroid.view.View;
- importandroid.widget.Button;
- importandroid.widget.ProgressBar;
- importandroid.widget.TextView;
- publicclassHandlerDemoActivityextendsActivity{
- privateButtonb1;
- privateButtonb2;
- privateButtonb3;
- privateButtonb4;
- privateProgressBarpb;
- privateTextViewtv;
- privateHandlerh1_post;
- privateHandlerh2_sendmessage;
- /**Calledwhentheactivityisfirstcreated.*/
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- b1=(Button)this.findViewById(R.id.button1);
- b2=(Button)this.findViewById(R.id.button2);
- b3=(Button)this.findViewById(R.id.button3);
- b4=(Button)this.findViewById(R.id.button4);
- pb=(ProgressBar)this.findViewById(R.id.progressBar1);
- tv=(TextView)this.findViewById(R.id.textView1);
- b1.setOnClickListener(buttonListener);
- b2.setOnClickListener(buttonListener);
- b3.setOnClickListener(buttonListener);
- b4.setOnClickListener(buttonListener);
- h1_post=newHandler();
- h2_sendmessage=newHandler(){
- @Override
- publicvoidhandleMessage(Messagemsg){
- pb.setProgress(msg.arg1);
- }
- };
- System.out.println("ThreadId:"+Thread.currentThread().getId());
- System.out.println("Threadname:"+Thread.currentThread().getName());
- }
- RunnableupdateProgressBar=newRunnable(){
- inti=0;
- @Override
- publicvoidrun(){
- System.out.println("ThreadId:"+Thread.currentThread().getId());
- System.out.println("Threadname:"+Thread.currentThread().getName());
- i+=10;
- pb.setProgress(i);
- try{
- Thread.sleep(3000);
- }catch(InterruptedExceptione){
- //TODOAuto-generatedcatchblock
- e.printStackTrace();
- }
- h1_post.post(updateProgressBar);
- if(i==100){
- h1_post.removeCallbacks(updateProgressBar);
- }
- }
- };
- RunnableupdateProgressBarThread=newRunnable(){
- inti=0;
- @Override
- publicvoidrun(){
- System.out.println("ThreadId:"+Thread.currentThread().getId());
- System.out.println("Threadname:"+Thread.currentThread().getName());
- while((i+=10)<=100){
- Messagemsg=h2_sendmessage.obtainMessage();
- msg.arg1=i;
- h2_sendmessage.sendMessage(msg);
- try{
- Thread.sleep(3000);
- }catch(Exceptione){
- e.printStackTrace();
- }
- }
- }
- };
- privateView.OnClickListenerbuttonListener=newView.OnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- switch(v.getId()){
- caseR.id.button1:
- h1_post.post(updateProgressBar);
- tv.setText("whichtest?:Test1");
- break;
- caseR.id.button2:
- newThread(updateProgressBarThread).start();
- tv.setText("whichtest?:Test2");
- break;
- caseR.id.button3:
- tv.setText("whichtest?:Test3");
- break;
- caseR.id.button4:
- tv.setText("whichtest?:Test4");
- break;
- }
- }
- };
- }
结果及说明:程序都是更新进度条操作。我在UI线程,即主线程中打印出了UI线程的ID和名字。
Button1,单纯的异步,我在它会调用的Run方法中也打印出了线程ID和名字。
结果:
显然,通过用Handler h1_post执行的run与主线程是同一个线程下面。
并且在点击Button1以后,我们再点击除了Button2的Button3和Button4会发现,用来显示which test?的字符串更新缓慢。按钮按下效果也会卡住,这些都是说明所有操作都在UI主线程的情况。
再看按下Button2的效果,是多线程异步的:
显然是两个线程了,而且点击其他的按钮反应也不会有卡住得感觉。
所以,在使用Handler的多线程异步时候一定要配合new Thread使用!或者也可以用Android提供的HandlerThread!
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- Android(安卓)Service的使用
- Android(安卓)四大组件(Activity、Service、BroadCastReceiver、
- Android(安卓)Fragment 体系 源码追踪笔记(4)
- 【ALearning】第五章 Android相关组件介绍(一)Activity
- Android消息处理
- Android(安卓)音效流程分析
- [置顶] android6.0源码分析之Activity启动过程
- Android(安卓)6.0 存储权限管理