每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作。如果在非UI线程直接对UI进行了操作,则会报错:
CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views。
Android为我们提供了消息循环的机制,我们可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让Ui线程来进行ui的操作。对于运算量较大的操作和IO操作,我们需要新开线程来处理这些繁重的工作,以免阻塞ui线程。
AsyncTask和Handler的优缺点比较:http://blog.csdn.net/onlyonecoder/article/details/8484200
ThreadHandlerActivity.activity
- public class ThreadHandlerActivity extends Activity {
- /** Called when the activity is first created. */
- private static final int MSG_SUCCESS = 0;//获取图片成功的标识
- private static final int MSG_FAILURE = 1;//获取图片失败的标识
- private ImageView mImageView;
- private Button mButton;
- private Thread mThread;
- private Handler mHandler = new Handler() {
- public void handleMessage (Message msg) {//此方法在ui线程运行
- switch(msg.what) {
- case MSG_SUCCESS:
- mImageView.setImageBitmap((Bitmap) msg.obj);//imageview显示从网络获取到的logo
- Toast.makeText(getApplication(), "成功!", Toast.LENGTH_LONG).show();
- break;
- case MSG_FAILURE:
- Toast.makeText(getApplication(), "失败!", Toast.LENGTH_LONG).show();
- break;
- }
- }
- };
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.threadhandler);
- mImageView= (ImageView) findViewById(R.id.threadhandler_imageView);//显示图片的ImageView
- mButton = (Button) findViewById(R.id.threadhandler_download_btn);
- mButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if(mThread == null) {
- mThread = new Thread(runnable);
- mThread.start();//线程启动
- }
- else {
- Toast.makeText(ThreadHandlerActivity.this, "线程已启动!", Toast.LENGTH_LONG).show();
- }
- }
- });
- }
- Runnable runnable = new Runnable() {
- @Override
- public void run() {//run()在新的线程中运行
- HttpClient hc = new DefaultHttpClient();
- HttpGet hg = new HttpGet("http://pic7.nipic.com/20100517/4945412_113951650422_2.jpg");//获取指南针图片
- final Bitmap bm;
- try {
- HttpResponse hr = hc.execute(hg);
- bm = BitmapFactory.decodeStream(hr.getEntity().getContent());
- } catch (Exception e) {
- mHandler.obtainMessage(MSG_FAILURE).sendToTarget();//获取图片失败
- return;
- }
- mHandler.obtainMessage(MSG_SUCCESS,bm).sendToTarget();//获取图片成功,向ui线程发送MSG_SUCCESS标识和bitmap对象
- }
- };
- }
threadhandler.xml
- <?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" >
- <Button
- android:id="@+id/threadhandler_download_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="ThreadHandler下载" >
- </Button>
- <ImageView
- android:id="@+id/threadhandler_imageView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
运行结果:
非UI线程发送消息到UI线程分为两个步骤
一、发送消息到UI线程的消息队列
通过使用Handler的
Message obtainMessage(int what,Object object)
构造一个Message对象,这个对象存储了是否成功获取图片的标识what和bitmap对象,然后通过message.sendToTarget()方法把这条message放到消息队列中去。
二、处理发送到UI线程的消息
在ui线程中,我们覆盖了handler的
public void handleMessage (Message msg)
这个方法是处理分发给ui线程的消息,判断msg.what的值可以知道mThread是否成功获取图片,如果图片成功获取,那么可以通过msg.obj获取到这个对象。
最后,我们通过
mImageView.setImageBitmap((Bitmap) msg.obj);
设置ImageView的bitmap对象,完成UI的更新。
相关推荐
### Android异步处理详解:使用Thread+Handler实现非UI线程更新UI界面 #### 概述 Android系统中,每一个应用程序都运行在一个独立的Dalvik虚拟机进程中。当应用程序启动时,系统会创建一个主线程(MainThread),也...
为了解决这个问题,Android提供了多种异步处理机制,其中一种常见的方式是使用`Thread`配合`Handler`来实现非UI线程执行耗时任务并更新UI。本篇将详细介绍这一方法。 首先,我们需要理解Android的线程模型。Android...
本篇文章将详细探讨两种常见的异步处理方式:`AsyncTask`和`Thread`配合`Handler`,并进行对比分析。 `AsyncTask`是Android SDK提供的一种轻量级的异步任务处理机制,它主要用于短时间的后台操作,如网络请求、数据...
在Android应用开发中,Handler、Thread和Looper是三个至关重要的组件,它们共同构成了Android线程间通信的基础架构。本文将详细解析这三个概念及其相互关系,旨在帮助开发者理解它们的工作原理和实际应用场景。 ...
在Android应用开发中,`Handler` 和 `Thread` 是两个非常关键的概念,它们主要用于处理线程间的通信和异步操作。下面将详细解释这两个概念,以及如何在实际应用中使用它们来实现简单的网络图片获取和显示。 首先,`...
本文将深入探讨两种主要的异步处理方式:线程(Thread)结合Handler以及AsyncTask,它们都是Android中用于解决此问题的有效工具。 1. **线程(Thread)与Handler**: - **线程**:在多线程环境中,线程是程序执行...
本文将对比分析Android中常见的三种异步处理方式:AsyncTask、ThreadPool(线程池)以及Thread+Handler,并通过实验研究它们在处理短时间内高并发场景时的性能表现。 首先,AsyncTask是Android提供的一种轻量级的...
在Android开发中,`Service`、`Thread`、`Toast`和`Handler`是四个非常重要的组件和概念,它们在创建高效、响应式的应用程序中起着关键作用。下面将详细阐述这些知识点及其相互关系。 首先,`Service`是Android中的...
在Android开发中,Thread和Handler是两个非常关键的概念,它们用于处理线程间通信和UI更新,确保程序的运行效率和用户体验。这篇博客主要探讨了如何有效地使用Thread和Handler进行多线程操作。 首先,Thread在Java...
本项目"Thread_Handler_MessageDownload"着重探讨了如何利用Thread、Handler和Message机制实现异步下载网络图片,确保UI线程不被阻塞,提高应用的响应速度。 首先,我们需要了解Android系统对线程的管理。在Android...
本教程将详细介绍三种在Android中下载网络数据的方法:AsynTask、Thread+Handler以及Volley。这三种方法各有特点,适合不同程度的开发者使用。 1. **AsynTask**: AsynTask是Android提供的一个轻量级异步任务框架...
### Android教程:深入理解MediaPlayer与MediaRecorder 在深入探讨如何在...在Android开发中,`Handler`、`Thread`、`TimerTask`以及它们的组合提供了强大的工具,可以帮助开发者创建高效且线程安全的应用程序。
在Android开发中,`Thread` 和 `Handler` 是两个非常重要的概念,它们是实现多线程通信的关键工具。本文将详细解析如何在`Thread`中使用`Handler`来修改主线程(UI线程)的数据或者更新UI。 首先,我们要了解`...
System.out.println("Handler-->"+Thread.currentThread().getName()); } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if ...
"WebView+Thread(内置Handler)实现应用内浏览器demo1" 这个标题揭示了我们将在一个Android应用程序中使用WebView组件,并结合线程(Thread)以及内置的Handler机制来创建一个简易的内置浏览器。这个"demo1"表明这...
在Android应用开发中,线程(Thread)和Handler是实现多任务并行处理以及界面更新的关键组件。Android系统是一个单线程模型,主线程(UI线程)负责处理用户交互和绘制界面,而其他工作通常需要在后台线程中执行,以...
本项目"Edu_AsyncTask.zip"显然关注于利用`AsyncTask`来实现在网页加载图片的异步操作,并对比了`AsyncTask`与`Thread + Message + Handler`的经典异步模型。 首先,我们深入理解`AsyncTask`。`AsyncTask`包含三个...
我们首先调用Thread.sleep方法来模拟一些耗时操作,然后使用Handler对象的post方法来更新UI。在post方法中,我们传入了一个Runnable对象,该Runnable对象将在主线程中执行,并更新UI。 布局文件中,我们定义了一个...
,这个题目有点意思,对于很多人来说,可能对Thread和Handler很熟悉,主要涉及到Android的消息机制(Handler、Message、Looper、MessageQueue),详见《 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及...
本文将深入探讨Android中的三种主要线程模式:Handler、Thread以及Looper,并结合源码分析它们的工作原理。 首先,我们来理解一下Android应用的基本运行环境。Android系统默认在主线程(UI线程)中执行所有的用户...