转载请注明出处:http://blog.csdn.net/yegongheng/article/details/38845953
我们知道,不管在任何的语言或操作系统平台(Android系统也不例外),多线程、多进程和异步任务的相关技术地讨论都是永恒的话题,很多的开发需求都需要使用多线程及异步任务以便实现多任务的同时执行和灵活的用户操作界面,而很多系统在使用过程中出现诸多莫名其妙的问题,都是由于开发人员使用多线程不当造成的,因此掌握在各个平台上的多线程及异步任务的原理和使用方法非常有必要。那从今天开始,我们将通过一系列的博文来学习在Android平台上的多线程以及异步任务的特点及使用方法,并一步步深入其源码,了解其实现机制。
每个Android应用程序都运行在单独的Davlik虚拟机中,当进程开启时会自动启动一个主线程(Main Thread),主线程主要负责与UI相关事件的交互,因此我通常将主线程又称之为UI线程。由于Android采用UI单线程模型,一般情况下,当应用程序执行比较耗时的操作时(例如文件读写、数据库操作和音频视频得下载等),为了防止由于线程执行时间过长而产生的UI线程阻塞,从而导致应用程序出现ANR(Application not response)的情况,我们通常会将该耗时操作放在新建的一个子线程中执行。但是因为UI是非线程安全的,我们又不能在子线程中对操作的结果进行UI元素的更新,只能在UI线程中进行,那怎么办呢?别急,Android类库提供的Handler类很好的解决了该问题。接下来我们将详细讲解Handler消息处理机的使用方法和原理:
概念:Handler是Android类库提供的用于接受、传递和处理消息或Runnable对象的处理类,它结合Message、MessageQueue和Looper类以及当前线程实现了一个消息循环机制,用于实现任务的异步加载和处理。下面有一张用于描述消息循环处理机制的关系图,如下:
上面这一张消息处理机制的关系图清晰地描述了使用Handler实现消息任务的异步加载和处理的一个整体流程,其中还涉及到了除Handler类之外的Message、MessageQueue和Looper类。那为了更进一步地使读者了解其中运行原理,我们来看看Handler、Message、MessageQueue和Looper这几个类的作用,如下:
Handler:将Message或Runnable对象传递到MessageQueue中,接收从MessageQueue分发出来的Message或Runnable对象;
MessageQueue:用于存放Message或Runnable对象的消息队列。它由对应的Looper对象创建,并由Looper对象管理;
Message:消息体,用于装载需要发送的对象;
Looper:循环不断地管理MessageQueue接收和分发Message或Runnable的工作。
了解了这些类的作用后,我们再来学习下它们之间有哪些关系。首先要明白的是,Handler和Looper对象是属于线程内部的数据,不过也提供与外部线程的访问接口,Handler就是公开给外部线程的接口,用于线程间的通信。Looper是由系统支持的用于创建和管理MessageQueue的依附于一个线程的循环处理对象,而Handler是用于操作线程内部的消息队列的,所以Handler也必须依附一个线程,而且只能是一个线程。基本了解了这四个类的各自职责和相互之间的关系后,我们再使用文字来描述一下整体消息处理机制的运行流程:
当应用程序开启时,系统会自动为UI线程创建一个MessageQueue(消息队列)和Looper循环处理对象,用户通过在UI线程创建的Handler不断地将Message(消息)或Runnable对象传递到MessageQueue中,Looper循环处理对象在系统的支持下管理着MessageQueue对Message或Runnable的接收和分发,另外Handler也接收从MessageQueue分发出来的特定的Message或Runnable对象。通俗地来讲,一般我们在实际的开发过程中用的比较多一种情况的就是主线程的Handler将子线程中处理过的耗时操作的结果封装成Message(消息),并将该Message(利用主线程里的MessageQueue和Looper)传递到主线程中,最后主线程再根据传递过来的结果进行相关的UI元素的更新,从而实现任务的异步加载和处理,并达到线程间的通信。
public class MainActivity extends Activity{ private ImageView mImageView ; private static final String TAG = "androidleaf"; private String urlStr = "http://img.my.csdn.net/uploads/201408/25/1408936379_4781.png" ; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView)findViewById(R.id.dialog_imageview ); } public void mainHanlderMainLooper(View view){ new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Bitmap mBitmap = HttpUtils.getBitmapFromNetWork(urlStr); //1、实例化一个Message对象 Message message = Message.obtain(); //将图片流赋值给Message对象 message. obj = mBitmap; //定义标签 message. what = 0; //3、发送消息到主线程中的Handler mHandler .sendMessage(message); } }).start(); } //2、在主线程中实例化Handler对象 Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); //4、接收消息并执行UI的更新操作 if (msg.obj != null) { Bitmap mBitmap = (Bitmap) msg.obj; mImageView .setImageBitmap(mBitmap); } else { Log. i( TAG, "Can not download the image source!!"); } } }; public void subHanlderMainLooper(View view){ new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Bitmap mBitmap = HttpUtils.getBitmapFromNetWork(urlStr); //实例化一个Message对象 Message message = Message.obtain(); //将图片流赋值给Message对象 message. obj = mBitmap; Handler mHandler3 = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super .handleMessage(msg); if (msg.obj != null) { Log. i( TAG, "使用子线程的Handler和主线程的Looper" ); } } }; mHandler3.sendMessage(message); } }).start(); } public void subHanlderSubLooper(View view){ new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Bitmap mBitmap = HttpUtils.getBitmapFromNetWork(urlStr); //1、创建Looper和MessageQueue对象 Looper. prepare(); //2、实例化Handler对象 Handler mHandler4 = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super .handleMessage(msg); //6、接收消息并执行UI的更新操作 if (msg.obj != null) { Log. i( TAG, "使用子线程的Handler和子线程的Looper" ); } } }; //3、实例化一个Message对象 Message message = Message.obtain(); //将图片流赋值给Message对象 message. obj = mBitmap; //4、发送消息 mHandler4.sendMessage(message); //5、开启消息循环机制 Looper. loop(); } }).start(); } public void welcome(View view){ Intent mIntent = new Intent(); mIntent.setClass(getApplicationContext(), WelcomeActivity.class ); MainActivity. this .startActivity(mIntent); } }
<?xml version= "1.0" encoding ="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <ScrollView android:layout_width= "fill_parent" android:layout_height= "fill_parent" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="30sp" android:textColor="#FF0000" android:text="Handler应用详解" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="主线程Handler主线程Looper" android:onClick="mainHanlderMainLooper" /> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:id="@+id/dialog_imageview" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="子线程Handler主线程Looper" android:onClick="subHanlderMainLooper" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="子线程Handler子线程Looper" android:onClick="subHanlderSubLooper" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="开启欢迎界面" android:onClick="welcome" /> </LinearLayout> </ScrollView> </LinearLayout>
public class WelcomeActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); //设置全屏 requestWindowFeature(Window. FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN ); setContentView(R.layout.welcome); welcomeMain(); } //欢迎界面方法 public void welcomeMain() { new Handler().postDelayed(new Runnable() { public void run() { //3000毫秒后跳转至WelcomeMainActivity界面 Intent mIntent = new Intent(WelcomeActivity.this , WelcomeMainActivity.class ); WelcomeActivity. this.startActivity(mIntent); WelcomeActivity. this.finish(); } //定时3000毫秒 }, 3000); } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/welcome_bg" tools:context="com.androidleaf.weixin.activity.SplashActivity"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:background="@drawable/welcome_earth" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@drawable/welcome_people" /> </RelativeLayout>