默认情况下,同一应用的所有组件会在相同的进程和线程中运行(主线程)。
若应用组件启动,该应用已存在进程(应用的其他组件存在),则组件会在该进程启动并用同执行线程。也可以安排组件在单独的进程中运行。
进程
默认情况下,应用的所有组件都在一个进程中运行。若需要管理其中某个组件的进程,可在清单文件中操作。
内存不足时,Android可能会决定在某一时刻关闭某个进程。是否终止某个进程取决于该进程中所运行组件的状态。
android:process:可指定组件应在哪个进程中运行。各类组件元素(< activity >,< service >,< receiver >,< provider >)的清单文件均支持android:process属性。可以通过设置属性,让组件均在各自的进程中运行或某些组件共享一个进程,也可以让不同应用的组件在同一进程中运行(前提是这些应用共享相同的Linux用户ID并使用相同的证书进行签署);< application >也支持process属性,可用来设置所有组件的默认值。
实现:
- 值以冒号开头的话,该进程就是私有进程,只有该app可以使用,其他应用无法访问;
- 不以冒号开头(如com.secondProcess),就是公有进程,
- 私有进程和公有进程的区别:私有进程其他应用不可以跑在同一个进程中;全局进程,其他应用可以通过设置相同的ShareUID可以和它跑在同一个进程
shareUID: 每个app都有唯一的linux userID【该应用程序的文件只对该用户可见,对该应用程序自身可见】让两个APK使用相同的userID,可以看到对方的文件。为了节省资源, 拥有相同ID的apk可以在相同的linux进程中进行,共享一个虚拟机。UID作用:数据共享,调用其他程序资源
线程
- 启动应用时,系统会为应用创建一个称为“main"(主线程)的执行线程。
- main线程负责将事件分派给相应的界面部件,包括绘图事件。应用与Android界面工具包组件(android.widget,android.view)也几乎都在该线程中进行交互。因此主线程有时也称为界面线程。
- 系统不会为每个组件实例创建单独的线程,同一进程中运行的组件都在界面线程中实例化,相关系统调用也由这个线程进行分配,响应系统回调的方法也在界面线程中运行。
- 当应用执行繁重的任务以响应用户交互时,单线程模式可能会导致性能低下。一旦被阻塞,线程将无法分派任何事件(时间过长会出现ANR)
- 单线程模式两条规则:不要阻塞UI线程;不要在UI线程之外访问Android UI工具包
工作线程
要保证应用界面的响应能力,不能阻塞UI线程。对于耗时的操作应放在单独的线程中运行(后台或工作线程)
从其他线程访问界面线程的几种途径(工作线程更新UI时需要返回到主线程)
#todo:调用,源码相关#
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
线程安全
系统可能会从多个线程调用所实现的方法,因此方法需要确保满足线程安全的要求
进程移除
Activity生命周期
阈值
- 根据阈值来判断需要移除进程的时机
- 进程等级越高,阈值越低
如前台进程阈值为172M,空进程为415M。当系统剩余内容不足415时,先回收空进程;当不足172M时,才去回收前台进程。
Home键,Back键,多任务键
Home键:点击的时候,App如果没有Service启动,则App会从一个前台进程转变为后台进程;如果有前台Service运行,则仍是前台进程;如果是普通Service运行,在变为服务进程;
Back键:如果没有Service开启,则从前台进程变为一个空进程;对于有Service运行,则和Home键一样;