Android开发过程中为什么要多线程
我们创建的Service、Activity以及Broadcast均是一个主线程处理,这里我们可以理解为UI线程。但是在操作一些耗时操作时,比如I/O读写的大文件读写,数据库操作以及网络下载需要很长时间,为了不阻塞用户界面,出现ANR的响应提示窗口,这个时候我们可以考虑使用Thread线程来解决。
Android中使用Thread线程会遇到哪些问题
对于从事过J2ME开发的程序员来说Thread比较简单,直接匿名创建重写run方法,调用start方法执行即可。或者从Runnable接口继承,但对于Android平台来说UI控件都没有设计成为线程安全类型,所以需要引入一些同步的机制来使其刷新,这点Google在设计Android时倒是参考了下Win32的消息处理机制。
postInvalidate()方法
对于线程中的刷新一个View为基类的界面,可以使用postInvalidate()方法在线程中来处理,其中还提供了一些重写方法比如postInvalidate(int left,int top,int right,int bottom) 来刷新一个矩形区域,以及延时执行,比如postInvalidateDelayed(long delayMilliseconds)或postInvalidateDelayed(long delayMilliseconds,int left,int top,int right,int bottom) 方法,其中第一个参数为毫秒,如下:
void |
|
void |
postInvalidate(int left, int top, int right, int bottom) |
void |
postInvalidateDelayed(long delayMilliseconds) |
void |
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom) |
Handler
当然推荐的方法是通过一个Handler来处理这些,可以在一个线程的run方法中调用handler对象的postMessage或sendMessage方法来实现,Android程序内部维护着一个消息队列,会轮训处理这些,如果你是Win32程序员可以很好理解这些消息处理,不过相对于Android来说没有提供PreTranslateMessage这些干涉内部的方法。
消息的处理者,handler负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现。将消息传递给Looper,这是通过handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法对其进行处理。
Handler主要接受子线程发送的数据,并用此数据配合主线程更新UI.
当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发,比如说,你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如:联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象,如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示 "强制关闭". 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的.这个时候,Handler就出现了,来解决这个复杂的问题, 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) ,把这些消息放入主线程队列中,配合主线程进行更新UI。
Handler一些特点:handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
它有两个作用: (1)安排消息或Runnable在某个主线程中某个地方执行
(2)安排一个动作在不同的线程中执行
Handler中分发消息的一些方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post类方法允许你排列一个Runnable对象到主线程队列中,sendMessage类方法,允许你安排一个带数据的Message对象到队列中,等待更新.
Handler实例
// 子类需要继承Hendler类,并重写handleMessage(Message msg) 方法,用于接受线程数据
// 以下为一个实例,它实现的功能为 :通过线程修改界面Button的内容
public class MyHandlerActivity extends Activity {
Button button;
MyHandler myHandler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentview(R.layout.handlertest);
button = (Button) findViewById(R.id.button);
myHandler = new MyHandler();
//当创建一个新的Handler实例时,它会绑定到当前线程和消息的队列中,开始分发数据
// Handler有两个作用, (1) :定时执行Message和Runnalbe对象
// (2):让一个动作,在不同的线程中执行.
//它安排消息,用以下方法
// post(Runnable)
// postAtTime(Runnable,long)
// postDelayed(Runnable,long)
// sendEmptyMessage(int)
// sendMessage(Message);
// sendMessageAtTime(Message,long)
// sendMessageDelayed(Message,long)
//以上方法以 post开头的允许你处理Runnable对象
//sendMessage()允许你处理Message对象(Message里可以包含数据,)
MyThread m = new MyThread();
new Thread(m).start();
}
/**
*接受消息,处理消息 ,此Handler会与当前主线程一块运行
* */
class MyHandler extends Handler {
public MyHandler() {
}
public MyHandler(Looper L) {
super(L);
}
//子类必须重写此方法,接受数据
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
Log.d("MyHandler", "handleMessage......");
super.handleMessage(msg);
//此处可以更新UI
Bundle b = msg.getData();
String color = b.getString("color");
MyHandlerActivity.this.button.append(color);
}
}
class MyThread implements Runnable {
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("thread.......", "mThread........");
Message msg = new Message();
Bundle b = new Bundle();//存放数据
b.putString("color", "我的");
msg.setData(b);
MyHandlerActivity.this.myHandler.sendMessage(msg); //向Handler发送消息,更新UI
}
}
}
Looper
其实Android中每一个Thread都跟着一个Looper,Looper可以帮助Thread维护一个消息队列,昨天的问题 Can't create handler inside thread 错误 一文中提到这一概念,但是Looper和Handler没有什么关系,我们从开源的代码可以看到Android还提供了一个Thread继承类HanderThread可以帮助我们处理,在HandlerThread对象中可以通过getLooper方法获取一个Looper对象控制句柄,我们可以将其这个Looper对象映射到一个Handler中去来实现一个线程同步机制,Looper对象的执行需要初始化Looper.prepare方法就是昨天我们看到的问题,同时推出时还要释放资源,使用Looper.release方法。
Looper是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象
创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。如需要接受,自己定义一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。
Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。
Message
对于Android中Handler可以传递一些内容,通过Bundle对象可以封装String、Integer以及Blob二进制对象,我们通过在线程中使用Handler对象的 sendEmptyMessage或sendMessage方法来传递一个Bundle对象到Handler处理器。对于Handler类提供了重写方法handleMessage(Message msg) 来判断,通过msg.what来区分每条信息。将Bundle解包来实现Handler类更新UI线程中的内容实现控件的刷新操作。相关的Handler对象有关消息发送sendXXXX相关方法如下,同时还有postXXXX相关方法,这些和Win32中的道理基本一致,一个为发送后直接返回,一个为处理后才返回。
Message:消息对象,Message Queue中的存放的对象。一个Message Queue中包含多个Message。 Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。除了上面这种方式,也可以通过Handler对象的obtainMessage()获取一个Message实例。
final boolean |
sendEmptyMessage(int what) |
final boolean |
sendEmptyMessageAtTime(int what, long uptimeMillis) |
final boolean |
sendEmptyMessageDelayed(int what, long delayMillis) |
final boolean |
sendMessage(Message msg) |
final boolean |
|
boolean |
sendMessageAtTime(Message msg, long uptimeMillis) |
final boolean |
sendMessageDelayed(Message msg, long delayMillis) |
MessageQueue
是一种数据结构,见名知义,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。
创建一个线程的时候,并不会自动创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。
java.util.concurrent对象分析
对于过去从事Java开发的程序员不会对Concurrent对象感到陌生吧,他是JDK 1.5以后新增的重要特性作为掌上设备,我们不提倡使用该类,考虑到Android为我们已经设计好的Task机制,我们这里Android开发网对其不做过多的赘述。
Task以及AsyncTask
在Android中还提供了一种有别于线程的处理方式,就是Task以及AsyncTask,从开源代码中可以看到是针对Concurrent的封装,开发人员可以方便的处理这些异步任务。 当然涉及到同步机制的方法和技巧还有很多,考虑时间和篇幅问题不再做过多的描
相关推荐
Android Handler详解-中国移动开发者社区 Android Handler详解-中国移动开发者社区
【Android_Handler01-源码】是一个关于Android Handler机制的源码分析项目。在Android开发中,Handler、Looper和Message是实现线程间通信的重要组件,尤其在UI更新和异步任务处理上扮演着核心角色。这个源码库可能是...
android-async-http-1.4.9.jar是一般使用Apache HTTP Client或者采用HttpURLConnect,但是直接使用这两个...所有的请求都是独立在UI主线程之外,通过回调方法处理请求结果,采用android Handler message 机制传递信息
【Android Handler 使用详解】 Handler 是 Android 平台中用于处理线程间通信的关键组件,尤其在涉及 UI(用户界面)更新时,它扮演着至关重要的角色。在 Android 应用程序启动时,系统会默认创建一个主线程,也...
Android Weak Handler Memory safer implementation of android.os.Handler Problem Original implementation of Handler always keeps hard reference to handler in queue of execution. Any object in Message or...
本文档主要讲述的是android-Handler整理总结;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
Handler是Android系统中用于线程间通信的重要工具,它允许开发者在不同的线程间传递消息并执行相应的处理。在Android应用开发中,由于主线程(UI线程)负责处理用户交互,因此耗时操作如网络请求、文件下载不应在...
android-async-http是专门针对Android在Apache的HttpClient基础上构建的异步http连接。所有的请求全在UI(主)线程之外执行,而callback使用了Android的Handler发送消息机制在创建它的线程中执行。
使用android-async-http这个库可以大大的简化操作,它是基于Apache’s HttpClient ,所有的请求都是独立在UI主线程之外,通过回调方法处理请求结果,采用android Handler message 机制传递信息
使用android-async-http这个库可以大大的简化操作,它是基于Apache’s HttpClient ,所有的请求都是独立在UI主线程之外,通过回调方法处理请求结果,采用android Handler message 机制传递信息
安卓开发中经常使用到的一个框架,使用android-async-http这个库可以大大的简化操作,它是基于Apache’s HttpClient ,所有的请求都是独立在UI主线程之外,通过回调方法处理请求结果,采用android Handler message ...
System.out.println("Handler-->"+Thread.currentThread().getName()); } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if ...
在上一篇文章《Android应用程序消息处理机制(Looper、Handler)分析》中,我们分析了Android应用程序的消息处理机制,本文将结合这种消息处理机制来详细分析Android应用程序是如何获得键盘按键消息的。
【Android_Handler详解(一)】 在Android开发中,Handler是一个至关重要的组件,它与线程、消息队列和Looper紧密关联,用于实现不同线程间的通信。本篇将深入探讨Handler的基本概念、使用方法以及其在多线程环境中的...
在Android开发中,`Handler`、`MediaPlayer`和`ThreadLocal`是三个非常重要的概念,它们在构建高效、响应式的应用程序中起到关键作用。本文将深入探讨这些知识点,帮助开发者理解它们的工作原理以及如何在实际项目中...
在Android开发中,`Handler`是一个至关重要的组件,它用于处理主线程中的消息调度,实现UI线程与后台线程之间的通信。`Handler`、`Looper`和`Message`是Android异步处理的核心三剑客,它们共同协作,保证了应用的...
- 上述内容已经详细解释了Handler的工作原理。 2. **如何避免Handler内存泄漏?** - 使用静态内部类定义Handler。 - 在Handler中使用弱引用指向外部Activity或其他对象。 - 明确释放资源,例如取消发送的消息等...
本篇文章将详细讲解Android性能优化的一些核心知识点,并以"Handler产生的内存泄露"作为其中一个实例进行深入探讨。 首先,我们要了解Android性能优化的主要目标:减少资源消耗、提高响应速度和降低功耗。这包括对...
11. **AsyncTask**和**Handler**:两者都是异步编程工具,AsyncTask适合短时间的后台任务,而Handler-Looper-Message机制适合更复杂的通信和定时任务。 12. **权限管理**:Android 6.0及以上版本引入了运行时权限,...