- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Android线程管理之ActivityThread由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
ActivityThread功能 。
它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client、ActivityThread.ApplicationThread为Server)负责调度和执行activities、broadcasts和其它操作.
在Android系统中,在默认情况下,一个应用程序内的各个组件(如Activity、BroadcastReceiver、Service)都会在同一个进程(Process)里执行,且由此进程的【主线程】负责执行.
在Android系统中,如果有特别指定(通过android:process),也可以让特定组件在不同的进程中运行。无论组件在哪一个进程中运行,默认情况下,他们都由此进程的【主线程】负责执行.
【主线程】既要处理Activity组件的UI事件,又要处理Service后台服务工作,通常会忙不过来。为了解决此问题,主线程可以创建多个子线程来处理后台服务工作,而本身专心处理UI画面的事件.
【主线程】的主要责任:
• 快速处理UI事件。而且只有它才处理UI事件, 其它线程还不能存取UI画面上的对象(如TextView等),此时, 主线程就叫做UI线程。基本上,Android希望UI线程能根据用户的要求做出快速响应,如果UI线程花太多时间处理后台的工作,当UI事件发生时,让用户等待时间超过5秒而未处理,Android系统就会给用户显示ANR提示信息.
只有UI线程才能执行View派生类的onDraw()函数.
• 快速处理Broadcast消息。【主线程】除了处理UI事件之外,还要处理Broadcast消息。所以在BroadcastReceiver的onReceive()函数中,不宜占用太长的时间,否则导致【主线程】无法处理其它的Broadcast消息或UI事件。如果占用时间超过10秒, Android系统就会给用户显示ANR提示信息.
注意事项:
• 尽量避免让【主线程】执行耗时的操作,让它能快速处理UI事件和Broadcast消息.
• BroadcastReceiver的子类都是无状态的,即每次启动时,才会创建其对象,然后调用它的onReceive()函数,当执行完onReceive()函数时,就立即删除此对象。由于每次调用其函数时,会重新创建一个新的对象,所以对象里的属性值,是无法让各函数所共享.
一:线程通信、ActivityThread及Thread类是理解Android线程管理的关键.
线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用。本小节主要从以下三个方面进行分析:
1.《Android线程管理——线程通信》 2.《Android线程管理——ActivityThread》 3.《Android线程管理——Thread类的内部原理、休眠及唤醒》 。
-------------------------------------------------------------------------------- 。
2、ActivityThread的主要工作及实现机制 。
ActivityThread是Android应用的主线程(UI线程),说起ActivityThread,不得不提到Activity的创建、启动过程以及ActivityManagerService,但本文将仅从线程管理的角度来分析ActivityThread。ActivityManagerService、ActivityStack、ApplicationThread等会在后续文章中详细分析,敬请期待喔~~不过为了说清楚ActivityThread的由来,还是需要简单介绍下.
以下引用自罗升阳大师的博客:《Android应用程序的Activity启动过程简要介绍和学习计划》 。
Step 1. 无论是通过Launcher来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都通过Binder进程间通信进入到ActivityManagerService进程中,并且调用ActivityManagerService.startActivity接口; 。
Step 2. ActivityManagerService调用ActivityStack.startActivityMayWait来做准备要启动的Activity的相关信息; 。
Step 3. ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread代表的是调用ActivityManagerService.startActivity接口的进程,对于通过点击应用程序图标的情景来说,这个进程就是Launcher了,而对于通过在Activity内部调用startActivity的情景来说,这个进程就是这个Activity所在的进程了; 。
Step 4. ApplicationThread不执行真正的启动操作,它通过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity; 。
Step 5. 对于通过点击应用程序图标来启动Activity的情景来说,ActivityManagerService在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动; 。
Step 6. ActivityManagerServic调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操作; 。
Step 7. ApplicationThread把这个启动Activity的操作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来.
大师的这段描述把ActivityManagerService、ActivityStack、ApplicationThread及ActivityThread的调用关系讲的很清楚,本文将从ActivityThread的main()方法开始分析其主要工作及实现机制.
ActivityThread源码来自:https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ActivityThread.java 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
static
void
main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"ActivityThreadMain"
);
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(
false
);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(
new
EventLoggingReporter());
AndroidKeyStoreProvider.install();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final
File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0(
"<pre-initialized>"
);
Looper.prepareMainLooper();
ActivityThread thread =
new
ActivityThread();
thread.attach(
false
);
if
(sMainThreadHandler ==
null
) {
sMainThreadHandler = thread.getHandler();
}
if
(
false
) {
Looper.myLooper().setMessageLogging(
new
LogPrinter(Log.DEBUG,
"ActivityThread"
));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw
new
RuntimeException(
"Main thread loop unexpectedly exited"
);
}
|
上述代码中,红色部分之前的代码主要用于环境初始化、AndroidKeyStoreProvider安装等,这里不做重点说明。红色部分的代码主要分为两个功能块:1)绑定应用进程到ActivityManagerService;2)主线程Handler消息处理.
关于线程通信机制,Handler、MessageQueue、Message及Looper四者的关系请参考上一篇文章《Android线程管理——线程通信》.
2.1 应用进程绑定 。
main()方法通过thread.attach(false)绑定应用进程。ActivityManagerNative通过getDefault()方法返回ActivityManagerService实例,ActivityManagerService通过attachApplication将ApplicationThread对象绑定到ActivityManagerService,而ApplicationThread作为Binder实现ActivityManagerService对应用进程的通信和控制.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private
void
attach(
boolean
system) {
sCurrentActivityThread =
this
;
mSystemThread = system;
if
(!system) {
…… RuntimeInit.setApplicationObject(mAppThread.asBinder());
final
IActivityManager mgr = ActivityManagerNative.getDefault();
try
{
mgr.attachApplication(mAppThread);
}
catch
(RemoteException ex) {
// Ignore
}
…… }
else
{
……
}
}
|
。
在ActivityManagerService内部,attachApplication实际是通过调用attachApplicationLocked实现的,这里采用了synchronized关键字保证同步.
1
2
3
4
5
6
7
8
9
|
@Override
public
final
void
attachApplication(IApplicationThread thread) {
synchronized
(
this
) {
int
callingPid = Binder.getCallingPid();
final
long
origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
|
attachApplicationLocked的实现较为复杂,其主要功能分为两部分:
thread.bindApplication mStackSupervisor.attachApplicationLocked(app) 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
private
final
boolean
attachApplicationLocked(IApplicationThread thread,
int
pid) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
if
(pid != MY_PID && pid >=
0
) {
synchronized
(mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
}
else
{
app =
null
;
}
// ……
try
{
// ……
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent,
new
Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app,
false
,
null
);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
}
catch
(Exception e) {
// todo: Yikes! What should we do? For now we will try to
// start another process, but that could easily get us in
// an infinite loop of restarting processes...
Slog.wtf(TAG,
"Exception thrown during bind of "
+ app, e);
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
startProcessLocked(app,
"bind fail"
, processName);
return
false
;
}
// See if the top visible activity is waiting to run in this process...
if
(normalMode) {
try
{
if
(mStackSupervisor.attachApplicationLocked(app)) {
didSomething =
true
;
}
}
catch
(Exception e) {
Slog.wtf(TAG,
"Exception thrown launching activities in "
+ app, e);
badApp =
true
;
}
}
// ……
}
|
thread对象其实是ActivityThread里ApplicationThread对象在ActivityManagerService的代理对象,故此执行thread.bindApplication,最终会调用ApplicationThread的bindApplication方法。该bindApplication方法的实质是通过向ActivityThread的消息队列发送BIND_APPLICATION消息,消息的处理调用handleBindApplication方法,handleBindApplication方法比较重要的是会调用如下方法:
mInstrumentation.callApplicationOnCreate(app),
callApplicationOnCreate即调用应用程序Application的onCreate()方法,说明Application的onCreate()方法会比所有activity的onCreate()方法先调用.
mStackSupervisor为ActivityManagerService的成员变量,类型为ActivityStackSupervisor.
/** Run all ActivityStacks through this */ ActivityStackSupervisor mStackSupervisor,
从注释可以看出,mStackSupervisor为Activity堆栈管理辅助类实例。ActivityStackSupervisor的attachApplicationLocked()方法的调用了realStartActivityLocked()方法,在realStartActivityLocked()方法中,会调用scheduleLaunchActivity()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
final
boolean
realStartActivityLocked(ActivityRecord r,
ProcessRecord app,
boolean
andResume,
boolean
checkConfig)
throws
RemoteException {
//...
try
{
//...
app.thread.scheduleLaunchActivity(
new
Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new
Configuration(mService.mConfiguration),
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
//...
}
catch
(RemoteException e) {
//...
}
//...
return
true
;
}
|
app.thread也是ApplicationThread对象在ActivityManagerService的一个代理对象,最终会调用ApplicationThread的scheduleLaunchActivity方法.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@Override
public
final
void
scheduleLaunchActivity(Intent intent, IBinder token,
int
ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int
procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean
notResumed,
boolean
isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState,
false
);
ActivityClientRecord r =
new
ActivityClientRecord();
……
sendMessage(H.LAUNCH_ACTIVITY, r);
}
|
同bindApplication()方法,最终是通过向ActivityThread的消息队列发送消息,在ActivityThread完成实际的LAUNCH_ACTIVITY的操作.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
void
handleMessage(Message msg) {
if
(DEBUG_MESSAGES) Slog.v(TAG,
">>> handling: "
+ codeToString(msg.what));
switch
(msg.what) {
case
LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"activityStart"
);
final
ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r,
null
);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break
;
……
}
|
handleLaunchActivity()用于启动Activity。具体的启动流程不在这里详述了,这里重点说明ApplicationThread及ActivityThread的线程通信机制.
2.2 主线程消息处理 。
在《Android线程管理——线程通信》中谈到了普通线程中Handler、MessageQueue、Message及Looper四者的关系,那么,ActivityThread中的线程通信又有什么不同呢?不同之处主要表现为两点:1)Looper的初始化方式;2)Handler生成.
首先,ActivityThread通过Looper.prepareMainLooper()初始化Looper,为了直观比较ActivityThread与普通线程初始化Looper的区别,把两种初始化方法放在一起:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public
static
void
prepare() {
prepare(
true
);
}
private
static
void
prepare(
boolean
quitAllowed) {
if
(sThreadLocal.get() !=
null
) {
throw
new
RuntimeException(
"Only one Looper may be created per thread"
);
}
sThreadLocal.set(
new
Looper(quitAllowed));
}
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public
static
void
prepareMainLooper() {
prepare(
false
);
synchronized
(Looper.
class
) {
if
(sMainLooper !=
null
) {
throw
new
IllegalStateException(
"The main Looper has already been prepared."
);
}
sMainLooper = myLooper();
}
}
|
•普通线程的prepare()方法默认quitAllowed参数为true,表示允许退出,ActivityThread在prepareMainLooper()方法中调用prepare()方法,参数为false,表示主线程不允许退出。 •普通线程只调用prepare()方法,ActivityThread在调用完prepare()方法之后,会通过myLooper()方法将本地线程<ThreadLocal>的Looper对象的引用交给sMainLooper。myLooper()其实就是调用sThreadLocal的get()方法实现的.
1
2
3
4
5
6
7
|
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public
static
Looper myLooper() {
return
sThreadLocal.get();
}
|
•之所以要通过sMainLooper指向ActivityThread的Looper对象,就是希望通过getMainLooper()方法将主线程的Looper对象开放给其他线程.
1
2
3
4
5
6
7
|
/** Returns the application's main looper, which lives in the main thread of the application.
*/
public
static
Looper getMainLooper() {
synchronized
(Looper.
class
) {
return
sMainLooper;
}
}
|
其次,ActivityThread与普通线程的Handler生成方式也不一样。普通线程生成一个与Looper绑定的Handler即可,ActivityThread通过sMainThreadHandler指向getHandler()的返回值,而getHandler()方法返回的其实是一个继承Handler的H对象。.
1
2
3
4
5
6
7
|
private
class
H
extends
Handler {
……
}
final
H mH =
new
H();
final
Handler getHandler() {
return
mH;
}
|
真正实现消息机制“通”信的其实是Looper的loop()方法,loop()方法的核心实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public
static
void
loop() {
final
Looper me = myLooper();
if
(me ==
null
) {
throw
new
RuntimeException(
"No Looper; Looper.prepare() wasn't called on this thread."
);
}
final
MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final
long
ident = Binder.clearCallingIdentity();
for
(;;) {
Message msg = queue.next();
// might block
if
(msg ==
null
) {
// No message indicates that the message queue is quitting.
return
;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if
(logging !=
null
) {
logging.println(
">>>>> Dispatching to "
+ msg.target +
" "
+
msg.callback +
": "
+ msg.what);
}
msg.target.dispatchMessage(msg);
if
(logging !=
null
) {
logging.println(
"<<<<< Finished to "
+ msg.target +
" "
+ msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final
long
newIdent = Binder.clearCallingIdentity();
if
(ident != newIdent) {
Log.wtf(TAG,
"Thread identity changed from 0x"
+ Long.toHexString(ident) +
" to 0x"
+ Long.toHexString(newIdent) +
" while dispatching to "
+ msg.target.getClass().getName() +
" "
+ msg.callback +
" what="
+ msg.what);
}
msg.recycle();
}
}
|
大致流程如下:
•首先通过上述myLooper()方法获取Looper对象,取出Looper持有的MessageQueue; •然后从MessageQueue取出Message,如果Message为null,说明线程正在退出; •Message不为空,则调用Message的target handler对该Message进行分发,具体分发、处理流程可参考《Android线程管理——线程通信》; •消息处理完毕,调用recycle()方法进行回收.
最后此篇关于Android线程管理之ActivityThread的文章就讲到这里了,如果你想了解更多关于Android线程管理之ActivityThread的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我最近在/ drawable中添加了一些.gifs,以便可以将它们与按钮一起使用。这个工作正常(没有错误)。现在,当我重建/运行我的应用程序时,出现以下错误: Error: Gradle: Execu
Android 中有返回内部存储数据路径的方法吗? 我有 2 部 Android 智能手机(Samsung s2 和 s7 edge),我在其中安装了一个应用程序。我想使用位于这条路径中的 sqlit
这个问题在这里已经有了答案: What's the difference between "?android:" and "@android:" in an android layout xml f
我只想知道 android 开发手机、android 普通手机和 android root 手机之间的实际区别。 我们不能从实体店或除 android marketplace 以外的其他地方购买开发手
自Gradle更新以来,我正在努力使这个项目达到标准。这是一个团队项目,它使用的是android-apt插件。我已经进行了必要的语法更改(编译->实现和apt->注释处理器),但是编译器仍在告诉我存在
我是android和kotlin的新手,所以请原谅要解决的一个非常简单的问题! 我已经使用导航体系结构组件创建了一个基本应用程序,使用了底部的导航栏和三个导航选项。每个导航选项都指向一个专用片段,该片
我目前正在使用 Facebook official SDK for Android . 我现在正在使用高级示例应用程序,但我不知道如何让它获取应用程序墙/流/状态而不是登录的用户。 这可能吗?在那种情
我在下载文件时遇到问题, 我可以在模拟器中下载文件,但无法在手机上使用。我已经定义了上网和写入 SD 卡的权限。 我在服务器上有一个 doc 文件,如果用户单击下载。它下载文件。这在模拟器中工作正常但
这个问题在这里已经有了答案: What is the difference between gravity and layout_gravity in Android? (22 个答案) 关闭 9
任何人都可以告诉我什么是 android 缓存和应用程序缓存,因为当我们谈论缓存清理应用程序时,它的作用是,缓存清理概念是清理应用程序缓存还是像内存管理一样主存储、RAM、缓存是不同的并且据我所知,缓
假设应用程序 Foo 和 Eggs 在同一台 Android 设备上。任一应用程序都可以获取设备上所有应用程序的列表。一个应用程序是否有可能知道另一个应用程序是否已经运行以及运行了多长时间? 最佳答案
我有点困惑,我只看到了从 android 到 pc 或者从 android 到 pc 的例子。我需要制作一个从两部手机 (android) 连接的 android 应用程序进行视频聊天。我在想,我知道
用于使用 Android 以编程方式锁定屏幕。我从 Stackoverflow 之前关于此的问题中得到了一些好主意,并且我做得很好,但是当我运行该代码时,没有异常和错误。而且,屏幕没有锁定。请在这段代
文档说: android:layout_alignParentStart If true, makes the start edge of this view match the start edge
我不知道这两个属性和高度之间的区别。 以一个TextView为例,如果我将它的layout_width设置为wrap_content,并将它的width设置为50 dip,会发生什么情况? 最佳答案
这两个属性有什么关系?如果我有 android:noHistory="true",那么有 android:finishOnTaskLaunch="true" 有什么意义吗? 最佳答案 假设您的应用中有
我是新手,正在尝试理解以下 XML 代码: 查看 developer.android.com 上的文档,它说“starStyle”是 R.attr 中的常量, public static final
在下面的代码中,为什么当我设置时单选按钮的外观会发生变化 android:layout_width="fill_parent" 和 android:width="fill_parent" 我说的是
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 9
假设我有一个函数 fun myFunction(name:String, email:String){},当我调用这个函数时 myFunction('Ali', 'ali@test.com ') 如何
我是一名优秀的程序员,十分优秀!