android中的进程与线程:
当一个应用程序启动第一个组件的时候,android会为它启动一个linux进程,并在其中执行一个单一的线程,默认的情况下所有的组件均在这个进程的这个线程中运行。也可以安排在其它的进程中运行。
进程:
前台进程
前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候。一般来说,在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。
可见进程
可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。
服务进程
运行着一个通过startService() 方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用户非常关注的任务(比如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。
后台进程
运行着一个对用户不可见的activity(调用过 onStop() 方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个activity正确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
空进程
未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。
组件运行的进程又manifest文件锁控制。组件元素 <activity> <service> <receiver> < provider>他们都有一个process属性来指定组件运行在那个进程中。
这些属性可以使每个组件运行在自己的进程中,也可以一些共享一个进程,而其它的不共享,也可以不同的应用程序的组件在同一个进程中运行。
所有的组件都位于特定的进程的主线程中,一般不会为每个实例创建一个线程,但是View.onKeyDown()和组件生命周期通告运行在主线程中。
当内存不足的时候会关闭一些进程来满足当前应用的需要。
线程:
一般会产生一个新的线程来处理后台任务,以为用户界面必须非常及时的反应用户的操作结果,所以一些网络下载之类的耗时的都应该安排到不同的线程中去执行。
Android 对进程的重要性评级的时候,选取它最高的级别。另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服务的进程重要级低。因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工作,而不是开启一个子进程??特别是这个操作需要的时间比activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片,使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。
单线程模型
当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
创建线程使用的是java中的Thread,用于管理线程的有:Looper Handler HandlerThread等操作。
线程安全:
同一时间内被多个线程执行的方法必须实现线程安全。
Activity:运行于主线程。因Android的GUI是非线程安全的,所有界面相关操作必须在主线程中完成,又因为即时响应的需要,主线程中不能进行耗时长的操作,如果有些操作既耗时又需要操作界面,就用消息机制吧。开子线程处理耗时操作,需要操作界面时给主线程发消息,把界面操作限制在主线程中。
Service:服务本体运行于主线程,但响应函数(就是onBind返回的对象的接口啦)就复杂了。如果跟客户在同一个进程的话,就直接在客户的线程中运行,否则就从服务所在进程维护的线程池里取出一个线程来运行,如果同时有多个进程请求服务的话,就同时产生多个线程来响应。所以,想要提供给别人使用的服务必须做成线程安全的,否则就不要提供第三方使用的接口好啦,免得别人自做多情。
Content provider:跟服务相似。不过数据提供者的响应函数是固定的:query(), insert(), delete(), update(), and getType()。数据库应该是安全的,自己做的就要加倍小心啦。
Broadcast receiver:运行于主线程。它就一个方法,运行时跟当前Activity一样,优先级超高,是不能被杀死的,但方法一返回,就打入冷宫,随时可能被害,即便它运行时派生了子线程也不能母凭子贵,母子双双被害,更是人间惨剧。所以receiver中通常启动服务来做耗时的后台操作,启动Activity或任务栏通知来做界面响应。
举例:
如果需要做大运算,取网络数据等,得用AsyncTask
AsyncTask
首先AsyncTask是一个抽象类,子类继承AsyncTask必须实现其抽象方法doInBackground(Params…)。同时我们还需要实现onPostExecute(Result),因为结果会在Result中返回。
AsyncTask的生命周期
AsyncTask的生命周期分为四部分,每部分对应一回调方法,我们只需实现这些方法中的某些需要用到的方法。程序执行过程中这些会自动调用它们。
- onPreExecute():任务执行之前执行,可在这显示进度条。
- doInBackground(Params…):后台执行,主要用于完成需要任务。执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
- onProgressUpdate(Progress…):主线程执行,用于显示任务执行的进度。
- onPostExecute(Result):主线程执行,任务执行的结果作为此方法的参数返回。
AsyncTask中的三种泛型
AsyncTask中的三种泛型类型为Params、Progress、Result。
- Params:启动任务参数,比如请求的资源地址。
- Progress:顾名思义,后台任务执行的百分比。
- Result:后台执行任务返回的结果。
AsyncTask的执行
AsyncTask只能在在主线程中创建实例,创建实例后使用execute(params)执行。任务仅会执行一次,如果想再调用就必须创建新的实例。
具体实现
首先我们先继承实现AsyncTask,然后在主线程的getView()里创建其实例execute().
1、实现AsyncTask