Processes 和 Threads 学习笔记

来源:互联网 发布:程序员表白神器 编辑:程序博客网 时间:2024/05/20 14:41

        一般情况下,当我们启动一个App的时候,Android系统就会新启一个Linux进程,内含一个可执行的线程,这个线程也就是主线程,通常也叫做UI线程。所有的component组件都是工作在这个主线程中。当然,你也可以将组件设置在不同的进程中运行或者一个进程分成很多个线程。

在manifest中<activity><service><receiver><provider>都支持android:process 属性可以设置组件运行的进程。在<application>中也可以设置所有组件的工作进程。

        当内存空间很少或者其他进程需要内存空间的时候,Android就会kill掉一部分的进程。当然这不是随意的,而是Android根据每个进程对于User的重要程度,程度由低到高依次kill。Android选择进程的保持或者杀掉,取决于运行在进程中的组件以及组件的状态。

在重要性分级中,可以分为5级,1——最高,最后kill,5——最低,最早kill

        1、Foreground process(前台进程):存在下列情况时,进程处于为前台进程:

        有正在于用户交互的Activity;有与用户交互的Activity绑定的Service;有明确要求运行在前台的Service(只是设置了Service 的等级而已,并非真正可见);有正在执行其生命周期函数的Service;有BroadcastReceiver正在执行onReceive。

        一般情况下,只有一些少部分的前台进程存在。他们只有在内存空间实在太少了,不然就不能继续运行和与用户交互的情况下,才会被不得已而Kill掉。

        2、Visible process(可见进程):进程中没有前台组件,不能与用户交互,但是在屏幕上依然可见。

        一般有以下情况:有一个Activity不运行在前台,已经调用onPause()方法;有一个Service与一个可见或者前台Activity绑定。则表示该进程是可见进程。可见进程是极其重要的,除非为了前台进程的运行的需要才被kill,

       3、Service Process(服务进程):

        一个进程通过startService()启动了一个服务,并不会进入上面两种level,那么则是服务进程。虽然服务进程不直接与用户交互,但它的执行也是用户所关心的。除非没有足够的空间,系统会一直保持它们的运行。

        4、Background Process(后台进程):

       当一个Activity执行了onStop则运行在后台,他们已与用户没有直接的关系了。系统可以随时kill掉他们,为上述三种进程腾出空间。通常,系统中会有很多的后台进程在运行。他们被保存在LRU列表里,最近最少使用的就会先被kill掉。

        5、Empty Process(空进程):

        当一个进程不再拥有活动的组件。唯一保留它的目的就是为了缓存,使下一次启动某个组件的时候,加快启动速度。系统在平衡进程缓存和内核缓存资源时,会kill他们。

       Android尽可能高的排列进程的等级。进程A基于进程B,则进程B的重要性大于等于进程A。需要长时间运行的操作,最好是用service,而不是启动一个线程。这样无论Activity发生什么,至少能保证Service Process 这个等级。Broadcast 采用了service而不是将耗时的操作放在一个线程中。当然,我们也知道,service 也工作在UI线程中,所以,一些耗时和可能阻塞UI线程的操作不要放大UI线程中。

        所有的组件都运行在UI线程中,它负责事件的分发,包括绘制事件。当App执行一些高强度的工作的时候,一个UI线程可能会表现的很糟糕。如果将长(时间)操作如网络连接,数据库查询。放到UI线程中,则会阻塞UI线程。 UI 线程一旦被阻塞,就不能正常运行了。如果阻塞时间超过5s,系统就会让你选择是否关闭程序了。

Android 的UI不是线程安全的。所以不能再其他worker 线程中操作UI。Android 单线程的模型的两条准则:

         1、不要阻塞UI线程

         2、不要在UI线程外访问Android UI toolkit

      在其他线程中访问UI线程,有以下三种方式:

       Activity.runOnUiTread(Runnable)、View.post(Runnable)、View.postDelayed(Runnable,long).

        如果要处理很复杂的操作,上述方式可能变得难懂或者难以维护。那么可以考虑用Handler,用来在worker 线程中处理来自UI线程的消息。可能最好的方式使用AsyncTask。用户执行一些阻塞性操作,并最后更新UI。

        多个线程要操作同一个方法或者变量的时候,要保证线程安全。

        Interprocess Communication(进程间通信):需要使用bindService,去绑定一个Service。

原创粉丝点击