Android消息机制,异步和多线程概述:
自从framework广泛应用后,我们不用面对赤裸裸的手机操作系统API,做一些重复而繁杂没有意义的事情.但天下没有免费的午餐,我们还是需要学会高效正确的使用不同的framework,很多处理某一特定问题的手法在不同的framework中,用起来都会有所不同的.今天我们主要学习andorid framework的使用.
在Android中,下层是Linux的核,但上层的java做的framework把这一切封装的密不透风.以消息处理为例,在MFC(
不知道是啥)中,我们可以用PreTranslateMessage等东东自由处理消息,在C#中,Anders Hejlsberg老大说了,他为我们通向底层开了一扇"救生窗",但很遗憾,在Android中,这扇窗户也被关闭了(至少我现在没发现...).
在Android中,你想处理一些消息(比如:Keydown之类的...),你必须寻找Activity为你提供的一些重载函数(比如 onKeyDown之类的...)或者是各式各样的listener(比如OnKeyDownListner之类的...).这样做的好处是显而易见的,越多的自由就会有越多的危险和越多的晦涩,条条框框画好了,用起来省心看起来省脑,这是一个设计良好的framework应该提供的享受.对于我目前的工程而言,我没有什么BT的需求在当前API下做不到的,google的设计ms还是很nice的.
但世界是残酷的,有的时候我们还是必须有机制提供消息的分发和处理的,因为有的工作是不能通过直接调用来同步处理的,同时也不能通过Activity中内嵌的消息分发和接口设定来做到,比如说事件的定时触法,异步的循环事件的处理,高耗时的工作等等.在Android中,它提供了一些蛮有意思的方式来做这件事情,它有一个android.os.Handler的类,这个类接受一个Looper参数,顾名思义,这是一个封装过的,表征消息循环的类.默认情况下,Handler接受的是当前线程下的消息循环实例,也就是说一个消息循环可以被当前线程中的多个对象来分发,来处理(在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理...).在实例化一个 handlerInstance之后,你可以通过sendMessage等消息发送机制来发送消息,通过重载handleMessage等函数来分发消息.但是该handlerInstance能够接受到的消息,只有通过handlerInstance.obtainMessage构造出来的消息(这种说法是不确切的,你也可以手动new一个Message,然后配置成该handlerInstance可以处理的,我没有跟进去分析其识别机制,有兴趣的自己研究下).也就是说A, B, C, D都可以来处理同一线程内的消息分发,但各自都只能处理属于自己的那一份消息,这抹杀了B想偷偷进入A领地,越俎代庖做一些非份之事的可能(从理论上看,B还是有可能把消息伪装的和A他们家的一样,这样做,不但兼顾了灵活性,也确保了安全性,用起来也会简单,我的地盘我做主,不用当心伤及无辜,左拥右抱是一件很开心的事情...
很显然,消息发送者不局限于自己线程,否则只能做一些定时,延时之类的事情,岂不十分无趣.在实例化Handler的时候,Looper可以是任意线程的,只要有Handler的指针,任何线程也都可以sendMessage(这种构造方式也很有意思,你可以在A线程里面传B线程的Looper来构造 Handler,也可以在B线程里构造,这给内存管理的方法带来很大的变数...).但有条规则肯定是不能破坏的,就是非UI线程,是不能触碰UI类的.在不同平台上有很多解决方式.我们通过android中的AsyncQueryHandler类来了解google官方的解决方案.
AsyncQueryHandler是Handler的子类,文档上说,如果处理ContentProvider相关的内容,不用需要自行定义一套东西,而可以简单的使用async方式.我想指代的就应该是AsyncQueryHandler类.该类是一个典型的模板类,为ContentProvider的增删改查提供了很好的接口,提供了一个解决架构,final了一些方法,置空了一些方法.通过派生,实例化一些方法(不是每个对 ContentProvider的处理多需要全部做增删改查,我想这也是该类默认置空一些方法而不是抽象一些方法的原因),来达到这个目的.在内部,该类隐藏了多线程处理的细节,当你使用时,你会感觉异常便利.以query为例,你可以这么来用:
// 定义一个handler,采用的是匿名类的方式,只处理query,因此只重写了
// onQueryComplete函数:
queryHandler = new AsyncQueryHandler(this.getContentResolver())
{
// 传入一个ContentResolver实例,所以必须在OnCreate后实例化该Handler类
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
// 在这里你可以获得一个cursor和你传入的附加的token和cookie。
// 该方法在当前线程下(如果传入的是默认的Looper话),可以自由设定UI信息
}
};
调用时只需要调用startQuery(int token, Object cookie, ContentURI uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)函数即可.
queryHandler.startQuery(token, cookie, uri, projection, selection, selectionArgs, sortBy);
可见,该类的使用是多么简单.
下面来说说多线程异步处理的解决策略的.他的基本策略如下:
1.当你实例化一个AsyncQueryHandler类时(包括其子类...),它会单独构造一个线程,这个线程里面会构建一个消息循环.
2.获得该消息循环的指针,用它做参数实例化另一个Handler类,该类为内部类.至此,就有了两个线程,各自有一个Handler来处理消息.
3.当调用onXXX的时候,在onXXX函数内部会将请求封装成一个内部的参数类,将其作为消息的参数,将此消息发送至另一个线程.
4.在该线程的Handler中,接受该消息,并分析传入的参数,用初始化时传入的ContentResolver进行XXX操作,并返回Cursor或其他返回值.
5.构造一个消息,将上述返回值以及其他相关内容绑定在该消息上,发送回主线程.
6.主线程默认的AsyncQueryHandler类的handleMessage方法(可自定义,但由于都是内部类,基本没有意义...)会分析该消息,并转发给对应的onXXXComplete方法.
7.户重写的onXXXComplete方法开始工作.
上述策略我是看不太明白,姑且放一边把,放着以后来继续体会,下面这段是对上述的进一步阐述,在继续看哈:
第一个AsyncQueryHandler的实例化会导致创建一个线程,从此该线程成为不死的东东,所有的ContentResolver相关的工作,都由该线程统一完成.个人觉得这种解决方式很赞.本来这个线程的生命周期就很难估量,并且当你有一个ContentProvider的请求的时候,判断你会做更多的类似操作并不过分.就算错了,花费的也只是一个不死的线程(与进程同生死共存亡...),换来的却是简单的生命周期管理和无数次线程生死开销的节约.同时另外一个很重要的问题,他并会涉及到单件中数据同步的问题,每个类都有各自的Handler类,彼此互不干扰,分发可以分别进行.当多个数据请求的时候,在同一个ContentResolver上进行的可能微乎其微,这就避免了堵塞.总而言之,这套解决办法和Android的整体设计算是天作之合了.
建议如果你有什么非ContentProvider操作,却需要异步多线程执行的话,模拟一套,是个不错的策略,当然,具体情况具体分析,生搬硬套是学不好马列主义的...android的消息机制,异步和多线程其实并不复杂,只要有心,就能够学会.
上面这段是个牛人的话语,我不晓得几时才可以搞明白,继续迷茫吧,希望时间不要太长
内容有点多,还是分2次贴上来吧
分享到:
相关推荐
一、Android线程基础 Android系统的主要线程被称为“主线程”或“UI线程”,负责处理用户界面的交互事件,如触摸事件、绘制视图等。由于Android系统的安全机制,长时间运行的任务会阻塞UI线程,导致应用无响应(ANR...
在Android应用开发中,多线程技术是必不可少的,它能帮助开发者实现高效的代码执行,提升用户体验,并确保应用程序的响应性。本资源包主要聚焦于Android平台上的多线程编程,包括理论概念、最佳实践以及实际应用案例...
在Android开发中,多线程管理是至关重要的技术,它涉及到应用的性能、用户体验以及资源的有效利用。...通过以上知识点的学习和实践,开发者可以有效地管理和优化Android应用的多线程,提升应用性能和用户体验。
通过这个"AnonymousThread"示例,你可以学习到如何在Delphi XE5中创建和管理Android平台的线程,以及如何处理线程间的同步和通信,这对于开发高效、稳定的跨平台应用程序至关重要。实践这些概念,你的Delphi Android...
这个"Android多线程分段下载源码"实例是一个很好的学习资源,它实现了文件的分块下载,并允许用户自定义线程数来控制下载速度和效率。下面我们将详细探讨这一技术。 首先,我们要理解什么是分段下载。传统的单线程...
在Android开发中,线程和View的...通过分析压缩包中的"08ThreadCtrlView"文件,我们可以深入学习和实践这些知识,进一步提升对Android多线程和UI更新的理解。在项目中灵活运用这些技术,能够提高应用的性能和用户体验。
对于Android开发初学者,`ThreadUtils`提供了一个很好的学习案例,帮助理解线程的基本概念和如何在不同线程间进行切换。在实际项目中,你可以根据需求对其进行扩展,例如添加更多的线程策略,如定时执行、线程池等。...
1. **创建线程**: 可以使用`Thread`类直接创建一个新线程,或者使用更现代的`AsyncTask`,`Handler`/`Looper`,或者`Runnable`与`ExecutorService`。考虑到这是一个简单的任务,`Thread`或`Runnable`配合`Looper`...
本文主要探讨的是如何在Android平台上实现单线程和多线程下载,这是一项重要的技术,尤其在处理大文件或者需要后台持续运行的任务时。我们将从源码分析、工具应用等方面进行详细讲解。 首先,我们了解下Android中的...
通过对这个demo的深入学习,学生能更好地理解Android多线程的工作原理和实践技巧。 总结来说,Android多线程的掌握对于开发者优化应用性能和提升用户体验至关重要。通过分析这个详细的demo,学生们可以逐步了解并...
在Android开发中,多线程是一项至关重要的技术,它使得应用程序能够同时执行多个任务,提升用户体验,特别是对于处理耗时操作如网络请求、大数据计算或长时间的IO操作时。本教程将带你深入理解Android中的多线程,并...
1. **文件分块**:首先,我们需要知道文件总大小并将其划分为多个部分,每个部分对应一个线程。 2. **创建下载线程**:为每个部分创建一个线程,每个线程负责下载相应部分的数据。 3. **保存下载进度**:在下载...
通过上述知识点的介绍,我们可以看到Android线程入门不仅仅是学习如何创建和操作线程,更重要的是理解如何在保持应用流畅性的同时,安全地更新UI并处理耗时操作。同时,这部分内容还强调了项目管理的重要性,尤其是...
本资源提供的"android 多线程下载源代码"是一个很好的学习资料,可以帮助开发者理解并实现这一功能。 多线程下载的基本原理是将一个大文件分割成多个小部分,然后在一个线程池中创建多个线程,每个线程负责下载文件...
通过阅读和学习这些代码,可以加深对Android多线程断点下载的理解,并且可以直接应用到实际项目中。 总之,Android多线程断点下载是提高用户体验的重要手段,封装好的接口可以让开发者更专注于业务逻辑,而不是复杂...
总的来说,Android多线程机制的核心在于通过主线程的Looper、MessageQueue和Handler进行线程间通信。这种方式保证了UI线程的安全性,避免了因其他线程直接操作UI而导致的不安全情况。理解并熟练运用这些概念对于开发...
通过安装`demo.apk`,你可以直观地看到多线程下载的运行效果,同时也可以参考代码学习具体的实现方法,这对于理解和掌握Android多线程下载技术非常有帮助。 总结,Android多线程下载是提升用户体验的重要手段,通过...
1. **创建线程池**:预读操作需要在后台线程中执行,以避免阻塞主线程,导致UI卡顿。可以使用`ExecutorService`创建一个线程池,配置合适的线程数量,根据应用需求平衡性能和资源消耗。 2. **预读策略**:设计合理...
在学习和实践中,理解Android线程模型和正确更新UI的方法对于提升应用性能和用户体验至关重要。确保遵循最佳实践,避免主线程阻塞,合理安排任务执行,以及正确处理线程间的通信。通过实践和调试,你将能熟练掌握...
在Android开发中,多线程下载是一项常见的技术,特别是在处理大文件或网络资源时,为了提高下载速度和用户体验,开发者通常会采用多线程来分块下载数据。Android Studio作为官方推荐的Android集成开发环境,提供了...