首先下载Android api 进行查阅 ,API下载地址:http://pan.baidu.com/s/1i33dTGT
以下的描写叙述假设那里错了,请大家吐槽,我也是第一次学习,共同进步
Handler能够分发Message对象和Runnable对象到主线程中,每一个Handler实例,都会绑定到创建他的线程中(通常是位于主线程),它有两个作用:
(1): 安排消息或Runnable 在某个主线程中某个地方运行,
(2)安排一个动作在不同的线程中运行。
Looper 是管理Message queue的类。
能够通过Looper.getMainLooper();获取主线程
以下通过两个实例来測试一下吧:
============================================ONE=================================================
第一个小Demo就是两个Button和一个ProgressBar ,xml文件的内容就不写了,直接看Activity的代码吧
package com.example.handler; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.app.Activity; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; public class MainActivity extends Activity { //声明各个控件 private Button start=null; private Button end=null; private ProgressBar progressbar=null; private Thread thread=null; //获取主线程(具体请看Android API 文档) Looper looper=Looper.getMainLooper(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //通过id找到他们 start=(Button)findViewById(R.id.start); end=(Button)findViewById(R.id.end); progressbar=(ProgressBar)findViewById(R.id.progressbar); // 为Button设置监听器 start.setOnClickListener(new StartButtonOnclickListener()); end.setOnClickListener(new EndButtonOnclickListener()); } //声明点解開始类 class StartButtonOnclickListener implements OnClickListener{ @Override public void onClick(View v) { progressbar.setVisibility(View.VISIBLE); thread=new Thread(){ int i=0; public void run(){ i+=10; Message msg=handler.obtainMessage(); msg.arg1=i; //让线程延迟 try{ Thread.sleep(2000); }catch(InterruptedException e){ e.printStackTrace(); } //Log.i("run", "run "+i+"%"); Log.i("run", Thread.currentThread().getName()+"===="); msg.sendToTarget(); } }; thread.start(); } } //结束的类 class EndButtonOnclickListener implements OnClickListener{ @Override public void onClick(View v) { //从message queue 中去掉run handler.removeCallbacks(thread); //让progressbar置成隐藏 progressbar.setVisibility(View.GONE); } } Handler handler = new Handler(looper){ public void handleMessage(android.os.Message msg) { int i =msg.arg1; //依据message中传来的參数控制进度条 /* * 由于安卓不同意我们在主线程之外的线程中对UI进行改动,所以我在新建的线程中仅仅是进行计数 * 然后将计数的结果通过message传递到主线程中,在主线程中更新进度条。 */ progressbar.setProgress(i); Log.i("run", Thread.currentThread().getName()); if(i<100){ handler.post(thread); }else{ handler.removeCallbacks(thread); progressbar.setVisibility(View.GONE); } }; }; /* * 第一次打印线程是在另外一个线程中,后面你的循环使用handler.post的话,这个runnable不会跑在子线程中, * 而是把runnable放入了handler绑定的target(在此为主线程)中相应的队列,然后在handleMessage中通过looper * 从队列取出runnable运行 */ }当我点击启动button后,调用的不是主线程的run,而是我新建的线程。 可是由于安卓不同意我们在主线程之外的线程中对UI进行改动,所以我在新建的线程中仅仅是进行计数,然后将计数的结果通过message传递到主线程中,在主线程中更新进度条。第一次运行,是在onclick中运行thread.start(); 这条语句运行的,所以第一次计数是在新的线程里;然后在新的线程里,又运行了msg.sendToTarget(); 这个触发了Handler的handleMessage()方法,在这种方法里通过handler.post(thread);第二次运行了计数(通过这样形成了循环),因为post的机制,是把post的内容放到Handler绑定的线程(代码中绑定的是主线程(looper获取的是主线程))的message queue中,所以我们看打印的结果是这种:
所以仅仅有一次是次线程运行的,剩余的都是主线程运行的。
====================================================================================SECOND===============================================================================
经过改进后:
package com.example.handler; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.app.Activity; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; public class MainActivity extends Activity { private Button start=null; private Button end=null; private ProgressBar progressbar=null; private Thread thread=null; private static boolean running=true; //获取主线程 Looper looper=Looper.getMainLooper(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //通过id找到他们 start=(Button)findViewById(R.id.start); end=(Button)findViewById(R.id.end); progressbar=(ProgressBar)findViewById(R.id.progressbar); start.setOnClickListener(new StartButtonOnclickListener()); end.setOnClickListener(new EndButtonOnclickListener()); } class StartButtonOnclickListener implements OnClickListener{ @Override public void onClick(View v) { progressbar.setVisibility(View.VISIBLE); thread=new Thread(){ int i=0; public void run(){ while(running){ i+=10; Message msg=handler.obtainMessage();//返回从全局消息池中一个新的消息 msg.arg1=i; //让线程延迟 try{ Thread.sleep(2000); }catch(InterruptedException e){ e.printStackTrace(); } Log.i("run", Thread.currentThread().getName()+"===="); msg.sendToTarget(); if(i>100){ //当计数超过一百时,跳出循环 running = false; } } } }; thread.start(); } } Handler handler = new Handler(looper){ public void handleMessage(android.os.Message msg) { int i =msg.arg1; progressbar.setProgress(i); Log.i("run", Thread.currentThread().getName()); if(i>100){ //假设进度条慢,进度条隐藏 progressbar.setVisibility(View.GONE); } }; }; class EndButtonOnclickListener implements OnClickListener{ @Override public void onClick(View v) { //点击取消button,分线程不再循环计数 running = false; //让progressbar置成隐藏 progressbar.setVisibility(View.GONE); } } }
通过设置一个Boolean变量后,当running为true时,循环计数,并调用handler.sendMessage(msg)为主线程传递计数结果
执行后是:
这种话就能够看出主次线程一次运行,通过次线程传值给主线程后,主线程改变ProgressBar的值。(这里记住安卓不同意我们在主线程之外的线程中对UI(主线程)进行改动)!
大家吐槽吧。。。