文章目录
一. CoroutineContext 协程上下文
public interface CoroutineContext {
public operator fun <E : CoroutineContext.Element> get(key: Key<E>): E?
public fun <R> fold(initial: R, operation: (R, CoroutineContext.Element) -> R): R
public operator fun plus(context: CoroutineContext): CoroutineContext =
if (context === EmptyCoroutineContext) this else context.fold(this) { ...}
public fun minusKey(key: Key<*>): CoroutineContext
//注意这里,这个key很关键
public interface Key <E : CoroutineContext.Element>
public interface Element : CoroutineContext {
public val key: Key<*>
public override operator fun <E : Element> get(key: Key<E>): E? =
if (this.key == key) this as E else null
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
operation(initial, this)
public override fun minusKey(key: Key<*>): CoroutineContext =
if (this.key == key) EmptyCoroutineContext else this
}
}
二. View类的dispatchTouchEvent源码
public boolean dispatchTouchEvent(MotionEvent event) {
// 处理辅助功能相关
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
2.1 Android 中的典型设计模式:位掩码(Bitmask)
为什么不直接用 viewFlags = true/false 来表示是否启用(enabled),而是要用位运算的方式(如 (viewFlags & ENABLED_MASK) == DISABLED)?
- 节省内存
一个布尔值(boolean)在 Java 中虽然逻辑上是 true/false,但在 JVM 中实际上占用 1 字节(8 bit)。
如果为每个状态都单独使用一个布尔变量,那么这些状态将占用 多个字节。
而如果使用 一个 int 型变量(32 bit) 来存储多个状态标志,就可以将这些状态压缩到 一个变量中,大大节省内存。 - 提高访问效率
CPU 对整型数据的访问和位运算效率远高于访问多个布尔变量。位运算(如 &、|、~)是底层硬件直接支持的,执行速度非常快。 - 便于扩展和组合
使用位掩码可以很方便地 组合多个状态:
三. Dialog源码
3.1 show方法
public void show() {
// 如果对话框已经在显示状态
if (mShowing) {
// 如果装饰视图(DecorView)存在
if (mDecor != null) {
// 如果窗口具有 FEATURE_ACTION_BAR 特性,则刷新 ActionBar 的菜单
if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
}
// 将 DecorView 设置为可见状态
mDecor.setVisibility(View.VISIBLE);
}
// 直接返回,不重复显示
return;
}
// 重置取消标志为 false,表示对话框未被取消
mCanceled = false;
// 如果对话框尚未创建,则调用 onCreate 方法
if (!mCreated) {
dispatchOnCreate(null);
} else {
// 如果已经创建过,但 DecorView 被移除过,需要处理配置变更(如屏幕旋转)
final Configuration config = mContext.getResources().getConfiguration();
mWindow.getDecorView().dispatchConfigurationChanged(config);
}
// 调用 onStart 生命周期方法
onStart();
// 获取 DecorView
mDecor = mWindow.getDecorView();
// 如果 ActionBar 为 null 并且窗口支持 ActionBar,则创建 WindowDecorActionBar
if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
final ApplicationInfo info = mContext.getApplicationInfo();
mWindow.setDefaultIcon(info.icon); // 设置默认图标
mWindow.setDefaultLogo(info.logo); // 设置默认 Logo
mActionBar = new WindowDecorActionBar(this); // 创建 ActionBar
}
// 获取窗口布局参数
WindowManager.LayoutParams l = mWindow.getAttributes();
boolean restoreSoftInputMode = false;
// 检查软键盘输入模式是否未设置 FORWARD_NAVIGATION 标志
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
// 添加 FORWARD_NAVIGATION 标志
l.softInputMode |= WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
restoreSoftInputMode = true;
}
// 将 DecorView 添加到 WindowManager 显示出来
mWindowManager.addView(mDecor, l);
// 如果之前修改了软键盘模式,则恢复
if (restoreSoftInputMode) {
l.softInputMode &= ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
}
// 标记对话框为正在显示状态
mShowing = true;
// 发送显示完成的消息,可能用于通知监听器
sendShowMessage();
}
四. ActivityThread
4.1 main方法
public static void main(String[] args) {
// 开始性能追踪,标记为 "ActivityThreadMain",用于调试和性能分析
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// 安装选择性系统调用拦截器,用于增强安全性或监控系统调用
AndroidOs.install();
// 关闭 CloseGuard(资源未关闭检测机制),避免日志过多
// 后续在调试构建中可通过 StrictMode 有选择地启用
CloseGuard.setEnabled(false);
// 初始化当前用户的运行环境(如路径、存储等)
Environment.initForCurrentUser();
// 确保证书存储模块使用正确的用户配置目录来加载 CA 证书
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
// 调用初始化与进程相关的 Mainline 模块(用于模块化系统更新)
initializeMainlineModules();
// 设置进程名称为 "<pre-initialized>",便于调试时识别
Process.setArgV0("<pre-initialized>");
// 为主线程准备 Looper,用于处理消息队列(MessageQueue)
Looper.prepareMainLooper();
// 从命令行参数中查找 "seq=xxx" 格式的进程启动序号
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
// 创建 ActivityThread 实例(Android 应用主线程的核心类)
ActivityThread thread = new ActivityThread();
// 将当前线程附加到系统进程中,传入启动序号
thread.attach(false, startSeq);
// 如果主线程的 Handler 未初始化,则获取当前线程的 Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// 可选:开启消息日志打印(默认关闭)
if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}
// 结束性能追踪
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// 启动主线程的消息循环,开始处理 UI 事件、Activity 生命周期等
Looper.loop();
// 如果 Looper.loop() 意外退出,抛出异常,主线程不应退出
throw new RuntimeException("Main thread loop unexpectedly exited");
}
2509

被折叠的 条评论
为什么被折叠?



