`
410063005
  • 浏览: 178129 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Android进程和线程

阅读更多

(译自Android SDK文档Processes and Threads, 不全)

一. 进程生命周期

 

There are five levels in the importance hierarchy. The following list presents the different types of processes in order of importance (the first process is most important and is killed last):

importance hierarchy.分为五个等级,最重要的进程最后被杀死。

1. Foreground progress前台进程

前台进程是用户完成当前任务必需的进程。满足以下条件之一的进程为前台进程:

Hosts用户正在与之进行交互的Activity

1)Hosts被用户正在与之进行交互的Activity绑定的Service

2)Hosts前台Service

3)Hosts正在执行onCreate()onStart()onDestroy()Service

4)Hosts正在执行onReceive()方法的BroadcastReceiver

通常情况下任意时刻仅有少量前台进程。前台进程仅在极端情况下才会被杀死,比如设备内存过低需要进行页面置换。

2. Visible progress可见进程

没有前台组件、但仍影响用户屏幕显示内容的进程即为可见进程。

1)Hosts Visible Activity,即不在前台、但仍然可见的Activity(已调用onPause())。比如某个原本处于前台的Activity弹出一个对话框,则这个Activity现在处于可见状态

2) HostsVisible Activity绑定的Service

可见进程非常重要,除非要保证前台进程运行,一般不会杀死可见进程

3. Service progress服务进程

通过startService()方法启动服务的 、且不属于以上两种情况的进程,归为服务进程。服务进程不直接跟用户所见产生关系,但它们通常执行一些用户非常关心的操作,比如在后台播放音乐或下载文件。

4. Background progress后台进程

Hosts对用户不可见的Activity(已调用onStop()方法)的进程为后台进程。这些进程不会对用户体验产生直接影响,所以系统可以在任何时候杀死它们以便为前台进程、可见进程、服务进程回收内存。通常同时存在许多后台进程,它们被保存在LRU(least recently used)队列中,以保证用户最近使用的Activity最后被杀死。如果一个Activity正确地实现了其生命周期方法,并且保存了当前状态,杀死该进程不会对用户体验产生明显影响。

5. 空进程

不持有任何应用组件的进程为空进程。空进程存在的意义是缓存,以加速下次组件的启动速度。

 

Android尽可能将一个进程往高级别排列。比如,某个进程hosts一个service和一个可见activity,则认为这个进程是可见进程而非服务进程。另外,一个进程的等级也可能因依赖关系而发生变化。一个进程为另一个进程提供服务,则前者等级绝对不可能比后者低。比如,A进程中的 一个content providerB进程中的一个客户提供服务,或者A进程中的一个serviceB进程中的某个组件绑定,则A进程至少与B进程有同样的优先等级。

 

由于运行service的进程级别比运行后台activity的进程级别高,发起长时间任务(long-running operation)activity最好通过服务来完成任务,而不是简单地创建一个工作线程,尤其当任务持续时间长过activity自身生命时。比如,一个activity上传图片到网站上,则该activity应当启动一个服务来完成上传操作,当用户离开这个activity时上传工作仍能继续。使用service能保证至少具有service progress优先级,不管这时activity状态如何。基于同样的理由,broadcast receiver也应当利用service而非创建线程来完成耗时操作。

 


二. 工作线程

程序启动时,系统创建一个main线程用户执行程序。Main线程非常重要,它负责分发事件到相应的UI部件,包括绘图事件(drawing events)Main线程有时也称作UI线程。

 

系统并不为每个组件实例创建单独的线程。进程中所有的组件都在UI线程中实例化,对每个组件的系统调用也都从该线程分发。结果,类似于onKeyDown()这样的系统调用都在这个进程的UI线程中运行。

 

单线程应用程序性能低下。如果所有的操作都在UI线程中进行,类似网络访问或数据库访问之类的耗时操作将会阻塞UI。当UI线程被阻塞,事件不能被分发和处理,包括drawing events。从用户角度,应用死掉了。更糟糕的是,当UI线程阻塞超过5秒钟将会提示ANR

 

此外,UI toolkit并非线程安全。所以不能在UI线程以外的其他线程操作UI组件。综上所述,归纳出以下两个简单规则:

1. 不要阻塞UI线程

2. 不要在UI线程以外的线程访问和操作UI组件

来看这段代码,它是一个click listener,用于启动一个线程下载图片并在一个ImageView中展示这个图片:

 

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
            mImageView.setImageBitmap(b);
        }
    }).start();
}

 一开始,代码看似一切正常。但仔细就会发现,它违反了以上第2条规则:不要从UI线程以外的其他线程访问和操作UI。以上代码会导致未定义和不可预料的程序行为,这种行为难以跟踪和分析。

 

为了解决这个问题,Android提供了几种方法以便能够从其他线程访问UI线程。方法如下:

1. Activity.runOnUiThread(Runnable)

2. View.post(Runnable)

3. View.post(Runnable, long )

所以,可以用第1种方法将代码改成下面这样

 

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}
 

 

 

现在的实现是线程安全的了:网络操作在一个单独的线程中完全,而且UI操作也是在UI线程中完成。但问题又来了,当操作变得复杂时,类似的代码会越趋复杂并且难以维护。为了能够在工作线程中完成更加复杂的操作,可以考虑在工作线程中使用Handler来处理来自UI线程的消息。有可能最好的解决方案是继承AsyncTask类,它可以简化需要与UI交互的工作线程。

AsyncTask允许你在UI上执行异步操作。它在工作线程中完成可能产生阻塞的操作,然后在UI线程中发布执行结果,不用自己编码操作线程或Handler。使用AsyncTask时,必须继承AsyncTask并且实现doInBackground()回调方法,这个方法在一个后台线程池中运行。为了能够更新UI,还必须实现onPostExecute(),该方法在UI线程中运行、并且能接收和处理doInBackground()的执行结果。这样,就能安全地更新UI了。

下面是使用AsyncTask来解决前面相同的问题。

 

public void onClick(View v) {
    new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls) {
        return loadImageFromNetwork(urls[0]);
    }
    
    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result) {
        mImageView.setImageBitmap(result);
    }
}
 

 

 

 

0
0
分享到:
评论

相关推荐

    Android 进程和线程

    在这个移动互联网新时代里,如果应用开发者具备更多的进程和线程知识,将能有更多空间与平台软件、硬件开发者沟通,这对创造开源、开放的Android应用软件系统是非常有帮助的。

    Android进程和线程详解

    Android进程和线程详解.当启动一个应用程序组件时,如果该应用没有正在运行的其它程序组件,那么Android系统将为这个应用创建一个新进程(包含一个线程)用于运行应用。  当启动一个应用程序组件时,如果该应用没有...

    线程和进程的区别,详细解释

    线程进程的区别于联系,详细介绍.希望对大家有用。如果有不足的地方,麻烦留言。

    Android Task 进程与线程详解

    关于Android中的进程和线程文档,看完后对 Android里面的Task概念有更深的了解。

    详解Android进程和线程

    写在前面的话 一个Android应用就是一个Linux进程,每个应用在各自...当某个应用组件启动且该应用没有运行其他任何组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。默认情况下,同一应用的所有组件在

    Android中的进程和线程

    Android中的进程和线程,新手入门教程,希望对大家有所帮助

    Android进程结束杀掉子线程Demo

    http://blog.csdn.net/qq_28690547/article/details/50375997;关于demo的文章详解,有兴趣的童鞋可以看看,解决popupwindow/dialog的BadTokenException异常

    android 进程与线程 - 开发文档翻译 - 进程.doc

    android 进程与线程 - 开发文档翻译 - 进程

    Android 进程和线程模型

    Android进程模型  在安装Android应用程序的时候,Android会为每个程序分配一个Linux用户ID,并设置相应的权限,这样其它应用程序不能访问此应用程序所拥有的数据和资源了。  在 Linux 中,一个用户ID 识别一个...

    掌握Android中的进程和线程

    Android作为一种的、承袭Linux的移动操作系统,其进程和线程的概念是开发者和安全工作人员需要深入了解的问题。本文将详细介绍Android中的进程、线程以及相关的技术问题。  进程和线程的基本概念  当一个应用...

    Android下线程与进程

    Android下线程与进程,详细可以参见博客:http://www.cnblogs.com/plokmju/p/android_ProcessOrThread.html

    Android 中三种启用线程的方法总结

    首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应。 而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。 ...

    安卓 进程/线程绑定cpu

    安卓开发时候,绑定线程/进程到指定cpu 上面.可以直接使用一个gradle项目 直接跑起来看效果 adb shell ps -t -p -c

    Android-可保持线程日志统一输出多线程不混乱

    可保持线程日志统一输出,多线程不混乱,比如多个请求时,每个请求的日志都是同时输出,而不是掺和成你一行我一行。但是可配置性没那么灵活,如果需要

    Android 应用程序模块 应用, 任务, 进程, 和线程--千锋培训

    文档介绍了引言,任务,任务亲和力(Affinities),启动模式以及启动标记,进程,线程

    Android_进程任务线程[参照].pdf

    Android_进程任务线程[参照].pdf

    Android开发应用实战详解源代码

    2.6 android进程和线程 2.6.1 进程 2.6.2 线程 2.6.3 远程调用(remote procedure calls) 2.7 intent消息传递 2.8 intent广播事件 2.8.1 广播事件 2.8.2 使用broadcast receiver监听广播 2.8.3 android本地广播 2.9...

    Android线程和进程介绍.pdf

    Android线程和进程介绍.pdf

    android进程和新城之间的通信

    android之间的进程和线程的通信

Global site tag (gtag.js) - Google Analytics