1、Android应用默认情况下同一应用的所有组件均在相同的进程中运行的
2、但是Android的4大组件都是支持指定该组件应在哪个进程运行的,<activity>
、<service>
、<receiver>
和 <provider>
—均支持添加android:process
属性
3、还可以通过设置android:process,还有运行时ID——android:sharedUserId为相同
,使不同应用的组件在相同的进程中运行,还需要两个应用打包的时候使用相同的证书。Android:process名称的不同还有不同的作用域:
"如果该属性指定名称以“:”开头,则一个新的专属于该应用的进程将会被创建。如果该进程名以小写字母开头,则为该activity提供权限以让其在一个全局的进程中运行。这样会允许多个应用的不同组件共用一个进程,以便节省资源。"
4、如果内存不足,其他应用有需要内存的时候,Android 可能会决定在某一时刻关闭某一进程。在被终止进程中运行的应用组件也会随之销毁。 当这些组件需要再次运行时,系统将为它们重启进程。 销毁的顺序遵循LRU的原则,保证最后用户看见的应用最后被kill。
在apk里面使用多进程有它的好处:
1、另外开辟一块内存空间来执行,不占用主进程的内存空间
2、有些应用守使用护进程和主进程之间相互监视,有一方被杀就重新启动它,使得应用的service常住内存
在实际项目中遇到了一个很郁闷的问题,在那个项目apk自动升级的时候一开始启动umeng的下载任务,就出现了异常,但是那个异常的调用栈和这个downloadingservice本身的代码没有任何关系,是application那个类里面onCreate的一段初始化的代码出现了异常。
<!-- umeng_update -->
<service
android:name="com.umeng.update.net.DownloadingService"
android:process=":DownloadingService" >
</service>
为啥会跑到application的那个onCreate里面去呢?原因是添加了android:process的组件相当于在单独的进程里面运行,也会执行application的onCreate一遍,所以如果有这种需要在另外的进程里面跑service或者其他组件的应用,一定要记得application的初始化要分清楚当前运行的process是否是需要做那些初始化的process否则可能会有意想不到的结果。判断当前进程名称的代码片段:
1 String getCurProcessName(Context context) {
2 //获得当前process的pid
3 int pid = android.os.Process.myPid();
4 //通过mActivityManager,遍历当前app正在跑的进程
5 ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
6 for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {
7 //如果pid和当前process的相等就是对应的进程名称
8 if (appProcess.pid == pid) {
9 return appProcess.processName;
10 }
11 }
12 return null;
13 }
对于默认的进程就是AndroidManifest里面<manifest配置的package比如下面的com.abc.app,
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abc.app"
而这个应用其它的进程就是这个package的名称+android:process配置的字符串,那个DownloadingService就是——“com.abc.app:DownloadingService”,大伙一定要记得在application初始化的时候根据判断当前的进程名称来初始化:)
应用启动时,系统会为应用创建一个名为“主线程”的执行线程。 它负责将事件分派给相应的用户界面小工具,其中包括绘图事件。 它负责应用与 Android UI 组件(来自 android.widget
和android.view
包)进行交互,也就是平时说的UI线程。
运行于同一进程的所有组件均在这个MainUI 线程中实例化,并且对每个组件的系统调用均由该线程进行分派。始终在进程的 UI 线程中运行。UI 线程从队列中取消该请求并通知小工具应该重绘自身。包括onclick ,onKeydown等事件也是在这个UI线程中执行的,请看下面的onclick的调用栈。
UI线程注意事项
此外,Android UI 工具包(android.widget
和android.view)
并非线程安全工具包。不能够通过非UI线程操作UI。因此,Android 的单线程模式必须遵守两条规则:
android.widget
和android.view
包)工具包,因为Android官方的说法是这些不是线程安全的,即使是setText("") z这个操作的结果也是不可预测的,Android提供了handler和runOnUiThread()两种方式来更新UI可以看看这篇http://www.2cto.com/kf/201302/190591.html对用法的讲解,后续我也会专门弄一篇来总结这两个的用法。就是通过获取当前线程的Looper和MainLooper是否相等来判断,大家可以去看看http框架volley在http请求完成之后回调用户的callback的时候,也是这样判断当前在不在主UI线程的。
public static boolean isInMainUIThread() { return Looper.myLooper() == Looper.getMainLooper(); }
具体原理可以看看下面的博客里面的分析
http://droidyue.com/blog/2014/07/12/check-main-thread-in-android-chinese-edition
原文:http://www.cnblogs.com/firebull/p/5081685.html