- 浏览: 715880 次
文章分类
- 全部博客 (324)
- 图片 (1)
- Javascript (25)
- Android (144)
- css (6)
- intellij (3)
- jquery (9)
- java (29)
- mysql (5)
- grails (1)
- groovy (1)
- Android Eclipse (2)
- linux (12)
- web (5)
- 算法 (2)
- 软件安装 (1)
- dedecms (12)
- centsos (6)
- tomcat (1)
- win 2003 (3)
- 杰奇 (1)
- window (1)
- loadrunner (3)
- QTP (38)
- VBS (33)
- Android 自动化 (12)
- python (3)
最新评论
-
masuweng:
Intellij 中javax.servlet.http.HttpServlet包导不进来 -
臧殿彬:
为什么我在主线程中定义也会出现这个bug?
java.lang.RuntimeException: Can't create handler inside thread that has not cal -
wpp1993:
...
http请求返回并解析json数据 -
javasea:
不错不错
socket阻塞与非阻塞,同步与异步、I/O模型 -
suyuwen1:
Apache2.4.x版wampserver本地php服务器如 ...
WAMPserver配置(允许外部访问、phpmyadmin设置为输入用户名密码才可登录等)
http://blog.csdn.net/flowingflying/article/details/6370184
程序需要相应用户的操作,最要能在200ms(0.2s)之内,如果超过5秒没有反应,ActivityManager会没有提示就kill了activity。然而,activity可能真的需要时间来进行处理,这往往会用到后台线程-background thread。后台线程可以安全地和UI线程进行交互,其中后台线程是不能修改UI的。我不太确切知晓“不能修改UI”到何种程度,例如在下面的例子进度条状态的修改是允许的,在复杂的例子中可能会出现问题,例如两个后台线程都要处理同一个widget,可能会有不可预知的情况出现,然而就编程而言,确实不应当如此处理,后台进程应避免涉及UI的处理,UI的归UI,处理的规处理。这样才是良好的编程风格或者是一种编程原则。
通过创建一个Handler子类的对象,每个acvivity只需一个Handler对象。后台进程可通过两种方式Handler进行通信:message和Runnable对象,其结果实质都是将在Handler的队列中放入内容,message是放置信息,可以传递一些参数,Handler获取这些信息并将判度如何处理,而Runnable则是直接给出处理的方法。队列就是依次执行,Handler会处理完一个消息或者执行完某个处理在进行下一步,这样不会出现多个线程同时要求进行UI处理而引发的混乱现象。
这些队列中的内容(无论Message还是Runnable)可以要求马上执行,延迟一定时间执行或者指定某个时刻执行,如果将他们放置在队列头,则表示具有最高有限级别,立即执行。这些函数包括有:sendMessage(), sendMessageAtFrontOfQueue(), sendMessageAtTime(), sendMessageDelayed()以及用于在队列中加入Runnable的post(), postAtFrontOfQueue(), postAtTime(),postDelay()。
一般而言,推荐是Messge方式,这样程序设计得可以更为灵活,而Runnable在某些简单明确的方式中使用。我们将通过三种方法编写一个小例子来学习。这个例子是一个进度条,每隔1秒,进度条步进5,如果acvity停止时,进度条归零。
Android XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ...... />
<ProgressBar android:id="@+id/c15_progress"
style="?android:attr/progressBarStyleHorizontal" <!-- 这表明采用传统水平进度条的方式-->
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
例子一:线程开启,采用Message传递后台线程和UI主线程之间的信息
public class Chapter15Test1 extends Activity{
private ProgressBar bar = null;
private boolean isRunning = false;
/* 我们为这个Acivity创建一个用于和后台程序通信的handler,简单地,只要一收到message,就将progressbar进度增加5。*/
/* 步骤1:创建Handler,并通过handleMessage()给出当收到消息是UI需要进行如何处理,例子简单不对msg的内容进行分析*/
Handler handler= new Handler(){
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chapter_15_test1);
bar=(ProgressBar)findViewById(R.id.c15_progress);
}
/*on Start是UI初始化并显示时调用*/
protected void onStart() {
super.onStart();
bar.setProgress(0);
/*步骤2:建立后台线程处理,采用Thread,其中run()的内容,就是线程并行处理的内容,Thread是Runnable的implements*/
Thread background = new Thread(new Runnable(){
public void run() {
try{
for(int i = 0; i < 20 && isRunning; i ++){
Thread.sleep(1000);
/* 步骤2.1:发送Message到队列中,参数中的obtainMessage()是用于给出一个新Message,本例无参数,对应的在handler在队列中收到这条消息时,则通过handleMessage()进行处理*/
handler.sendMessage(handler.obtainMessage());
}
}catch(Throwable t){
//jest end the thread
}
}
});
isRunning = true;
/*步骤3:启动线程*/
background.start();
}
/*onStop是UI停止显示时调用,例如我们按了返回键*/
protected void onStop() {
super.onStop();
isRunning = false;
}
}
例子2:采用Runnable
我们在上面的例子的基础上进行修改,如下
/*步骤1:由于不需要处理Message,也即不需要处理handleMessage()*/
Handler handler= new Handler();
/*步骤1.1:定义处理动作,采用Runnable的实例,通过implements run()来定制处理,这里是简单将进度条步进5。由于我们将在Thread中使用这个实例,所以考虑采用final的方式*/
final Runnable r = new Runnable(){
public void run(){
bar.incrementProgressBy(5);
}
};
/* ... ...在onStart()中的步骤2:线程的处理,和提供message不同,对于runnable方式,采用post */
Thread background = new Thread(new Runnable(){
public void run() {
try{
for(int i = 0; i < 20 && isRunning; i ++){
Thread.sleep(1000);
handler.post(r);
}
}catch(Throwable t){
//jest end the thread
}
}
});
background.start();
例子3:可以用延迟处理实现定时触发,让程序更为简单
在这里例子,事实我们是进行定时的处理,利用Handler队列可以设置延期处理的方式,我们并不需要创建一个后台运行的线程,也可以实现
Handler handler= new Handler();
... ... 在onStart() ... ...
//利用handler.postDelayed(r,1000),在队列中要求延迟1秒后进行r的处理,而在r的处理中, 最后在handler的队列中加 入一个要求延迟1秒的处理,如是,就可以实现每隔1秒的定期处理。
handler.postDelayed(new Runnable(){
public void run() {
if(isRunning && Chapter15Test2.step < 20){
step ++;
bar.incrementProgressBy(5);
handler.postDelayed(this, 1000);
}
}
},1000);
在这个例子中,我们基础某种判度,自动停止向队列加入处理。如果有某种情况,我们需要清除队列中的消息或者理,可以使用removMessages()或者removeCallbacks()的处理,这种对于延迟处理方式是非常有用的,可以中断定期的处理。当然,一般来讲我们希望能够得到某种判度,以使得定期处理能够优雅地结束,而不是简单地从队列中将消息或者处理删除。
例子4:不知道在UI主线程还是在后台线程
有时候,我们并不清楚代码将在UI线程还是后台线程运行,例如这些代码封装为一个JAR,提供给其他人调用,我们并不清楚其他人如何使用这些代码。为了解决这个问题Android在activity中提供了runOnUiThread(),如果在UI线程,则马上执行,如果在后台线程,则将Runnable的执行内容加入到后台线程的队列中,这样无论代码在UI线程还是后台线程都能安全地执行。
我们在例子1的基础上进行试验:
1、建立一个Runnable,以便我们将在UI和后台Thread中进行试验
Runnable runAction = new Runnable(){
public void run(){
//注意,我们不能使用Toast.makeText(this,....),因为我们无法确定Runnable具体运行的context
Toast.makeText(getApplicationContext(),"Hello!",Toast.LENGTH_SHORT).show();
//Log.d("WEI","runAction .... is called");
}
};
由于Toast的显示和隐藏需要一定的时间,而间隔1秒显然不够,我们将例子1的间隔时间1000ms,改为5000ms这样会比较清晰,当然可以采用Log.d的方式来替代。
2、在UI线程中执行该操作,在后台线程中增加该操作,这个操作无论是在UI还是在后台线程都是可以正确执行的。
protected void onStart() {
... ...
Thread background = new Thread(new Runnable(){
public void run() {
try{
for(int i = 0; i < 20 && isRunning; i ++){
Thread.sleep(5000);
handler.sendMessage(handler.obtainMessage());
runOnUiThread(runAction);
}
}catch(Throwable t){
//jest end the thread
}
}
});
isRunning = true;
background.start();
runOnUiThread(runAction);
}
例子5:HandlerThread
在上面的例子中,无论是否使用了后台线程(例子1-2),Handler的处理实际就是UI主线程的处理,一般的使用方式为我们通过后台线程执行某些操作,如果需要进行UI的互动,将消息或者处理方式到Handler的的队列中,然手在UI主线程中进行处理。这是我们通用的情况。
之前我们讨论过为何UI的归UI,处理的处理,然而,可能有这样的需求,举个例子,在某些情况下,Handler收到消息触发的处理中可能会有Sleep(),这会导致main线程进入sleep状态,不是我们期待的。因此我们希望通过一个线程专门处理Hanlder的消息,这个线程也是依次从Handler的队列中获取信息,逐个进行处理,保证安全,不会出现混乱引发的异常。
针对此Android提供的HandlerThread。方式使用方法如下:
//步骤1:创新HandlerThread的一个对象,并开启这个线程,HandlerThread将通过Looper来处理Handler对来中的消息,也就是如果发现Handler中有消息,将在HandlerThread这个线程中进行处理。
HandlerThread ht = new HandlerThread("hander_thread");
//步骤2:启动handerhandler这个线程;
ht.start();
//步骤3:创建handler中,带上Looper的参数,即handlerThread.getLooper()。注意,此处理必须在HandlerThread启动后才能调用,否则会报错 ,getLooper()会返回null,则程序异常出错
Handler handler = new Handler(ht.getLooper()){
....
public void handleMessage(Message msg){
... ... /*这里的处理,将不在主线程中执行,而在HandlerThread线程中执行,可以通过Thread.currentThread().getId()或者Thread.currentThread().getName()来确定*/
}
};
发表评论
-
将博客搬至CSDN
2014-12-24 22:28 857将博客搬至CSDN -
[Android设计模式]Android退出应用程序终极方法
2014-01-08 16:41 674首先,我们将管理Activity的功能通过一个扩展的Appl ... -
android中activity的四种加载模式
2014-01-08 16:20 938一、何为加载模式 在android的多activit ... -
Android实现数据存储技术
2014-01-08 13:49 884本文介绍Android中的5种数据存储方式。 数据存 ... -
-Android各版本系统源代码下载
2014-01-07 16:39 906原文地址http://blog.csdn.net/wangj ... -
XmlPullParser解析xml文件
2014-01-07 15:55 23959XML解析三种方式 DOM 通用性强,它会将XML文 ... -
ListView实现二级菜单
2014-01-06 18:53 3041实现如上图所示的二级菜单: 1上面是通过两个ListVi ... -
三种方式实现自定义圆形进度条ProgressBar
2014-01-06 16:46 3389一、通过动画实现 定义res/anim/loading.x ... -
android屏幕适配不同的资源图片、布局
2014-01-06 16:35 11951、 资源图片的适配: 在android ... -
获取屏幕分辨率 及 dp 和 像素关系
2014-01-06 16:24 1807DisplayMetrics metric = new Di ... -
Android用Application设置全局变量以及使用
2014-01-03 16:44 808如果想在整个应用中使用全局变量,在java中一般是使用静态变 ... -
Android SDK各版本源码
2013-06-07 20:47 1424http://repository.grepcode.com ... -
在android系统中增加预编译apk(use BUILD_PREBUILT instead!. Stop)
2013-06-05 22:55 103801,在commom.mk(build/target/prod ... -
android out目录结构
2013-06-02 14:37 1506Android编译完成后,将 ... -
Android OpenGL ES 开发教程 从入门到精通
2013-05-25 09:17 1060Android OpenGL ES 简明开发教程 An ... -
自定义ContentProvider
2013-05-20 19:10 1499自定义ContentProvider,根据不同的条件查询不同 ... -
Broadcast Receiver(广播接收器)
2013-05-19 23:11 1090Braodcast Receiver顾名思义就是广播接收器, ... -
Android Service生命周期及用法!
2013-05-19 22:22 1085来自:http://blog.csdn.net/andro ... -
Androdi Droid Fu介绍
2013-05-19 10:01 1213Droid-Fu是啥 Droid ... -
自定义dialog 含listview(二)
2013-05-16 12:13 2261弹出一个半透明的listview dialog: publ ...
相关推荐
总结来说,`Handler`、`Message`和`Runnable`是Android多线程编程中的核心工具,它们提供了安全、有序的线程间通信和UI更新机制,是开发高效、响应性良好的Android应用不可或缺的一部分。在实际项目中,开发者需要...
Handler是Android中用于线程间通信的工具,它可以发送和处理Message对象。Message对象通常包含处理结果或者命令,Handler会根据Message的what字段来区分不同的消息类型。 在上述示例中,我们创建了一个Handler实例...
### 浅谈Android线程模型:深入理解与实践 #### 引言 随着智能手机的普及和技术的不断进步,Google的Android操作系统成为了移动设备领域的重要力量。Android不仅为用户提供了丰富的功能,也为开发者提供了广阔的...
首先,理解Android线程模型至关重要。Android应用的主要工作线程被称为UI线程或主线程,它负责处理用户界面的更新和事件响应。后台线程通常用于执行耗时任务,避免阻塞UI线程。为了在后台线程和主线程之间交换数据和...
### Java/Android线程使用深度解析 在计算机科学领域,线程与进程是核心概念,尤其是在多任务操作系统中。本文将深入探讨Java/Android环境下的线程管理,包括线程的创建、线程池的利用及`ThreadHandler`的运用等...
Handler是Android中的一个关键组件,它用于在特定线程中发送和处理Message或Runnable对象。Handler有两个核心方法:`sendMessage()`和`handleMessage()`. `sendMessage()`可以在任何线程中调用,将消息放入消息队列...
4. Thread与Runnable:直接创建Thread对象或者实现Runnable接口,然后在新线程中运行。 5. ExecutorService:Java提供的线程池服务,可以更有效地管理和控制并发任务。 三、线程同步与通信 1. Synchronized关键字:...
`Handler`、`Message`和`Looper`是Android系统提供的一个关键机制,用于在不同的线程间进行通信,特别是主线程(UI线程)与工作线程间的交互。下面将详细解释这三个组件以及它们如何协同工作。 1. **Handler...
总结,理解和掌握Android线程管理是提升应用性能的关键。通过合理使用不同类型的线程和同步机制,开发者可以构建出既高效又稳定的Android应用程序。在实际项目中,根据任务特性和需求选择合适的线程模型,能显著提高...
总结一下,Android的Handler、Runnable和Looper机制是多线程编程的关键工具,它们提供了异步处理和UI更新的能力。理解并熟练运用这三个组件,对于编写高效、流畅的Android应用至关重要。在实际开发中,根据业务需求...
总结来说,Android的线程消息机制是通过Handler、Looper和Message Queue协同工作,实现线程间的通信和任务调度。它允许开发者在后台线程执行耗时操作,同时保持主线程的响应性,是构建高性能Android应用不可或缺的一...
本讲将深入探讨Android线程的使用,特别是如何利用Handler来实现在主线程中更新UI。Handler是Android中的一个消息处理机制,它与Looper和Message紧密配合,用于在不同的线程间传递消息并执行相应的回调方法。 1. **...
在Android开发中,线程和View的交互是十分常见的需求,因为Android的UI操作必须在主线程中进行,而耗时的操作(如网络请求、大数据处理等)则应该放在子线程中。本实例主要探讨如何在子线程中更新View,通过两种方式...
本文将深入解析Android线程启动的方法,并通过源代码示例帮助初学者理解和掌握这一关键技能。 Android系统基于Java,因此其线程机制遵循Java的基本规则,但同时也有一些特定于Android平台的特性。在Android中,主要...
- **主线程**:Android应用的UI线程,负责处理用户交互和更新界面。 - **工作线程**:用于执行耗时任务,防止阻塞主线程导致应用无响应(ANR)。 2. **创建线程的方式**: - **继承Thread类**:重写`run()`方法...
4. Handler/Message:Android特有的主线程与子线程通信机制,通过发送和处理Message实现数据交换。 四、Android游戏开发中的多线程应用 1. 渲染线程:负责游戏画面的渲染,通常使用OpenGL ES进行图形处理,确保帧率...
7. **线程安全**:MessageQueue的插入和删除操作是线程安全的,这得益于Android系统对其实现的同步机制,确保了多线程环境下的正确性。 8. **性能优化**:了解MessageQueue的工作原理有助于优化应用性能,例如避免...
在主线程即UI线程外,新建一个Looper线程,并用Messenger和Handler来处理message和posted runnable。程序中,在负线程中默认加了一个3s的线程等来,来帮助理解sent message和post runnable之间的同步机制。所以在按...
在Android开发中,多线程管理是至关重要的技术,它涉及到应用的性能、用户体验以及资源的有效利用。...通过以上知识点的学习和实践,开发者可以有效地管理和优化Android应用的多线程,提升应用性能和用户体验。
通过上述知识点的介绍,我们可以看到Android线程入门不仅仅是学习如何创建和操作线程,更重要的是理解如何在保持应用流畅性的同时,安全地更新UI并处理耗时操作。同时,这部分内容还强调了项目管理的重要性,尤其是...