首页 > 移动平台 > 详细

Android进程和UI线程小结及注意事项

时间:2015-12-29 06:13:28      阅读:319      评论:0      收藏:0      [点我收藏+]

Android应用运行的进程

1、Android应用默认情况下同一应用的所有组件均在相同的进程中运行的

2、但是Android的4大组件都是支持指定该组件应在哪个进程运行的,<activity><service><receiver> 和 <provider>—均支持添加android:process 属性

3、还可以通过设置android:process,还有运行时ID——android:sharedUserId为相同,使不同应用的组件在相同的进程中运行,还需要两个应用打包的时候使用相同的证书。Android:process名称的不同还有不同的作用域:

"如果该属性指定名称以“:”开头,则一个新的专属于该应用的进程将会被创建。如果该进程名以小写字母开头,则为该activity提供权限以让其在一个全局的进程中运行。这样会允许多个应用的不同组件共用一个进程,以便节省资源。"

4、如果内存不足,其他应用有需要内存的时候,Android 可能会决定在某一时刻关闭某一进程。在被终止进程中运行的应用组件也会随之销毁。 当这些组件需要再次运行时,系统将为它们重启进程。 销毁的顺序遵循LRU的原则,保证最后用户看见的应用最后被kill。

对于android:process 使用的注意事项

在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初始化的时候根据判断当前的进程名称来初始化:)

 

UI线程

      应用启动时,系统会为应用创建一个名为“主线程”的执行线程。 它负责将事件分派给相应的用户界面小工具,其中包括绘图事件。 它负责应用与 Android UI 组件(来自 android.widget 和android.view 包)进行交互,也就是平时说的UI线程。

      运行于同一进程的所有组件均在这个MainUI 线程中实例化,并且对每个组件的系统调用均由该线程进行分派。始终在进程的 UI 线程中运行。UI 线程从队列中取消该请求并通知小工具应该重绘自身。包括onclick ,onKeydown等事件也是在这个UI线程中执行的,请看下面的onclick的调用栈。

技术分享

UI线程注意事项

此外,Android UI 工具包(android.widget 和android.view)并非线程安全工具包。不能够通过非UI线程操作UI。因此,Android 的单线程模式必须遵守两条规则:

  1. 不要阻塞 UI 线程,包括响应onclick,onkeydown等,大约超过5秒不响应就会报,可能会ANR(Application Not Responding),耗时的操作都放到其他线程异步执行,然后通知UI线程更新
  2. 不要在 UI 线程之外访问 Android UI ( android.widget 和android.view 包)工具包,因为Android官方的说法是这些不是线程安全的,即使是setText("") z这个操作的结果也是不可预测的,Android提供了handler和runOnUiThread()两种方式来更新UI可以看看这篇http://www.2cto.com/kf/201302/190591.html对用法的讲解,后续我也会专门弄一篇来总结这两个的用法。

另外如何判断当前线程是否是UI线程

 就是通过获取当前线程的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

 

Android进程和UI线程小结及注意事项

原文:http://www.cnblogs.com/firebull/p/5081685.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!