博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
进程和线程
阅读量:4310 次
发布时间:2019-06-06

本文共 2567 字,大约阅读时间需要 8 分钟。

进程和线程

标签(空格分隔): Android API指导


此文档介绍Android应用的进程和线程是如何工作的。

进程

默认的,同一个应用中的所有组件都是运行在同一个进程。

所有组件在manifest文件中可以通过android:process属性来指定运行的进程。

进程生命周期

Android系统会给每个进程分级,如果系统需要回收内存时,就先销毁优先级低的进程,各层级如下(序号越高,重要性越低,越容易被销毁):

  1. 前台进程

    用户正在使用的,有如下场景:

    • 与用户交互的Activity界面(onResume已经执行)
    • 绑定到与用户正在交互界面的Service
    • 在前台运行的Service(用startForeground启动)
    • 正在执行生命周期回调函数的Service(onCreate、onStart、onDestroy)
    • 正在执行onReceiver的BroadcastReceiver

一般来说,某个时间点上只有少数的前台进程在运行。他们只有在内存低到无法继续运行的时候才有可能会被销毁。

  1. 可视进程

    进程不包含前台组件,但仍是用户可见的,有如下场景:

    • Activity不在前台,但是仍然是可见的(onPause已经执行),例如A弹出前台对话框B,B不能完全覆盖A时。
    • 绑定到可见或者前台Activity的service
  2. 服务进程
    由startService启动的服务,并且不在1和2场景中。
  3. 后台进程
    承载不可见的Activity(onStop已经执行)
  4. 空进程

    不承载任何组件的进程

线程

Android UI是单线程模型,应用中所有组件的实例都在同一个UI线程中执行,当UI线程阻塞时,会无法分发用户的点击事件导致ANR。

另外,UI线程是非线程安全的,所有与用户界面相关的交互必须都放在UI线程中,而不是用其他工作线程,因此,对于Android线程模型来说有两条简单的规则:

  1. 不要阻塞UI线程
  2. 不要在UI线程之外的其他线程中访问UI元素

工作线程

对于第一条规则,可以将耗时的操作放在新线程中,比如咋新线程中下载一个图片:

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

但是上述代码又违反了第二条规则,在非UI线程中使用了界面元素mImageView。

为了避免这个问题,Android提供了如下方法:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)

例如,可以这么用:

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();}

然而对于复杂的操作,上述代码很难维护,你可以使用Handler来处理,也可以扩展AsyncTask类

使用AsyncTask

AsyncTask允许执行UI元素的异步操作,它会在工作线程中执行阻塞UI的操作,然后将结果发送给UI线程,而不需要你自己处理线程。

使用方法:继承AsyncTask,实现在后台线程池执行的doInBackground,实现onPostExecute来更新UI。
例子:

public void onClick(View v) {    new DownloadImageTask().execute("http://example.com/image.png");}private class DownloadImageTask extends AsyncTask
{ /** 系统在工作线程中执行这个动作,其中入参是由AsyncTask.execute()提供 */ protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); } /** 系统调用这个刷新UI界面,其中result是doInBackground()的返回值 */ protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); }}
  1. AsyncTask用之前,建议看一下SDK文档
  2. 运行时的配置变化(比如横竖屏)会销毁你的工作线程,可以查看Shelves例子代码。

    线程安全方法

    某些情况下,你写的方法可能被多个线程调用,那就需要这个方法是线程安全的。

    像Service的onBind,ContentProvider的query、insert、delete、update、getType都是类似需要线程安全的函数。

    进程间通讯

    IPC,RPC,详见Service章节

转载于:https://www.cnblogs.com/konger/p/3978246.html

你可能感兴趣的文章
时间长了不用,什么都忘了
查看>>
Eclipse 配置Activiti插件
查看>>
正则符号
查看>>
mysql事件
查看>>
小米系统获取root权限的完整教程
查看>>
hdu1114Piggy-Bank(完全背包)
查看>>
迷宫城堡 HDU - 1269 (强连通分量)
查看>>
eigenface资料整合
查看>>
jquery tree的使用
查看>>
JS构造函数、原型对象、隐含参数this
查看>>
delegate 与 event 不得不说的关系~
查看>>
Bootstrap 基础讲解2
查看>>
获取ServletContext
查看>>
七周成为数据分析师07_统计学基础
查看>>
变革之心
查看>>
IAP Store Kit Guide(中文)
查看>>
VS 2012 ASPX 页面编辑器的一点改进
查看>>
Python单元测试框架——unittest
查看>>
django序列化 serializers
查看>>
Centos7忘记root密码,修改root密码及其他用户密码
查看>>