Android面试高频问题

1. 四大组件

        Activity, Service, ContentProvider, BroadcastReceiver.

2. Activity生命周期

一、生命周期方法(7个核心回调)
  1. onCreate()
    • 首次创建 Activity 时调用,用于初始化布局(如 setContentView())和数据绑定‌。
  2. onStart()
    • Activity 可见但未进入前台,用户无法交互(如后台加载资源)‌。
  3. onResume()
    • Activity 进入前台并获得焦点,用户可进行交互(如点击按钮)‌。
  4. onPause()
    • Activity 失去焦点但部分可见(如弹窗覆盖),需保存临时数据或释放资源‌。
  5. onStop()
    • Activity 完全不可见(如被其他界面覆盖),可能被系统回收内存‌。
  6. onDestroy()
    • Activity 被销毁前调用,释放长期占用的资源‌24。
  7. onRestart()
    • Activity 从停止状态重新回到可见前调用(如用户返回应用)‌。
二、生命周期流程
  • 完整启动流程‌:
    onCreate → onStart → onResume
  • 从后台返回前台‌:
    onRestart → onStart → onResume
  • 退出或销毁流程‌:
    onPause → onStop → onDestroy
  • 特殊情况‌:若快速返回(如短暂覆盖),可能跳过 onStop 直接执行 onPause → onResume‌。
三、状态与生命周期关联
  1. 运行状态(Active/Running)
    • Activity 处于栈顶,可见且可交互(对应 onResume 阶段)。
  2. 暂停状态(Paused)
    • 部分可见但无焦点(如弹窗存在时),可能被系统回收(对应 onPause 阶段)‌。
  3. 停止状态(Stopped)
    • 完全不可见,保留成员信息但可能被系统终止(对应 onStop 阶段)‌。
  4. 销毁状态(Destroyed)
    • Activity 被销毁或未启动,资源完全释放(对应 onDestroy 阶段)‌。
四、开发注意事项
  • 数据保存‌:在 onPause() 中保存临时数据,避免因内存回收丢失‌。
  • 资源释放‌:在 onStop() 或 onDestroy() 中释放数据库连接等长期占用资源‌。
  • 避免耗时操作‌:onPause() 和 onStop() 中不宜执行耗时任务,否则影响用户体验或导致 ANR‌。

3. ANR

ANR(Application Not Responding)解析

一、定义

ANR即‌应用程序无响应‌,是Android系统中检测到主线程被阻塞超过特定时间后触发的错误机制。此时系统会向用户弹窗提示,用户可选择等待或强制关闭应用‌。

二、触发条件

当主线程未在规定时间内完成以下操作时触发:

  1. Activity‌:5秒内未处理输入事件(如点击)‌;
  2. BroadcastReceiver‌:前台广播10秒、后台广播60秒未完成处理‌;
  3. Service‌:前台服务20秒、后台服务200秒未完成生命周期回调(如onStart)‌;
  4. ContentProvider‌:10秒内未执行完操作‌。
三、根本原因

主线程被‌耗时操作阻塞‌,例如:

  • 复杂的UI布局计算或大数据处理‌;
  • 同步I/O操作(如文件读写、数据库查询)‌;
  • 网络请求未异步执行‌。
四、影响与重要性
  1. 用户体验‌:频繁ANR会导致用户流失‌;
  2. 系统机制‌:ANR是Android保护应用响应性的核心机制,通过强制弹窗避免长期卡顿‌;
  3. 性能指标‌:ANR率是衡量应用流畅度的重要指标‌。
五、典型场景示例
  • 主线程中直接执行网络请求且等待响应‌;
  • 未使用异步任务处理大型图片加载或数据解析‌;
  • BroadcastReceiver.onReceive()中执行耗时逻辑且未异步化‌。

4. Activity启动模式

Activity 启动模式详解

一、核心模式分类与行为
  1. Standard(标准模式)

    • 行为‌:默认模式,每次启动均创建新实例并压入任务栈,允许同一 Activity 存在多个实例‌。
    • 生命周期‌:完整执行 onCreate → onStart → onResume‌。
    • 应用场景‌:需独立展示新内容的页面(如新闻详情页)‌。
  2. SingleTop(栈顶复用模式)

    • 行为‌:若目标 Activity 已处于栈顶,直接复用实例并回调 onNewIntent(),否则创建新实例‌。
    • 生命周期‌:复用时不触发 onCreate 和 onStart,仅调用 onNewIntent → onResume‌。
    • 应用场景‌:避免重复打开同一页面(如通知跳转页)‌。
  3. SingleTask(栈内复用模式)

    • 行为‌:若任务栈中存在目标 Activity 实例,清除其上方所有 Activity 使其位于栈顶,否则创建新实例‌。
    • 生命周期‌:复用实例时调用 onNewIntent → onResume,原实例以上的 Activity 被销毁‌。
    • 应用场景‌:应用主界面(确保全局唯一入口)或需全局状态管理的页面‌。
  4. SingleInstance(单实例模式)

    • 行为‌:目标 Activity 独占一个独立任务栈,其他应用启动该 Activity 时复用该实例‌。
    • 生命周期‌:首次启动时完整生命周期,后续复用触发 onNewIntent → onResume‌。
    • 应用场景‌:全局唯一性需求(如来电界面)或跨应用共享的页面‌。

二、关键特性对比
启动模式任务栈规则实例复用条件典型场景
Standard允许同一栈中多个实例无复用,每次新建动态生成新内容的页面(如新闻详情)‌
SingleTop仅复用栈顶实例目标 Activity 位于栈顶防止重复打开同一页面(如通知跳转)‌
SingleTask清除栈内上方 Activity 复用实例目标 Activity 存在于栈中主界面或核心功能页(如首页)‌
SingleInstance独占独立任务栈全局唯一实例跨应用共享或独立进程页面(如来电界面)‌

三、配置方式
  1. AndroidManifest 声明‌:

    <--通过 android:launchMode 属性指定‌-->
    <activity android:name=".MainActivity" android:launchMode="singleTask" />
    
  2. Intent Flags 动态设置‌:

    //优先级高于Manifest声明
    Intent intent = new Intent(this, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    

    四、开发注意事项
    1. 避免滥用 SingleTask‌:随意使用可能导致任务栈混乱(如误清用户操作历史)‌。
    2. 正确处理 onNewIntent()‌:在复用实例时需在此方法中更新数据和界面‌。
    3. 多任务栈管理‌:SingleInstance 模式需注意跨栈跳转时的返回逻辑‌。

    通过合理选择启动模式,可优化任务栈管理、提升用户体验,并减少资源消耗‌。

    5. 安卓线程间通信方式

    一、主线程与子线程通信
    1. Handler 机制

      • 原理‌:通过消息队列实现异步通信,子线程发送 Message 或 Runnable 对象到主线程的 Handler,主线程通过 Looper 循环处理消息‌。
      • 实现‌:
        // 主线程创建 Handler
        Handler handler = new Handler(Looper.getMainLooper());
        // 子线程发送消息
        new Thread(() -> {
            Message msg = handler.obtainMessage();
            msg.obj = "更新UI";
            handler.sendMessage(msg);
        }).start();
        
    2. AsyncTask

      • 原理‌:封装后台任务与UI更新逻辑,通过 doInBackground() 执行耗时操作,onPostExecute() 在主线程更新UI‌。
      • 注意‌:已过时,建议结合协程或 ExecutorService 替代‌。
    3. runOnUiThread

      • 原理‌:在 Activity 中直接切换至主线程执行代码,适用于简单UI操作‌。
      • 实现‌:
        new Thread(() -> {
            runOnUiThread(() -> textView.setText("结果"));
        }).start();
        
    4. View.post()

      • 原理‌:通过 View 对象直接提交 Runnable 到主线程消息队列‌。
      • 示例‌:
        imageView.post(() -> imageView.setImageBitmap(bitmap));
        

    二、子线程间通信
    1. 同步工具

      • CountDownLatch/Semaphore‌:通过计数器或信号量协调多个子线程的执行顺序‌。
        CountDownLatch latch = new CountDownLatch(2);
        new Thread(() -> { task1(); latch.countDown(); }).start();
        new Thread(() -> { task2(); latch.countDown(); }).start();
        latch.await(); // 等待所有子线程完成
        
    2. 共享内存+锁机制

      • 原理‌:使用 synchronized 或 ReentrantLock 保护共享资源,避免竞态条件‌。
      • 风险‌:需谨慎处理死锁和性能问题‌。

    三、其他通信方式
    1. BroadcastReceiver

      • 原理‌:通过发送广播实现跨线程/组件通信,需注册接收器并定义 IntentFilter‌。
      • 场景‌:适用于全局事件通知(如网络状态变化)‌。
    2. EventBus

      • 原理‌:第三方库通过发布-订阅模式实现解耦通信,支持线程切换‌。
      • 示例‌:
        EventBus.getDefault().post(new MessageEvent("数据"));
        

    四、核心注意事项
    • 避免主线程阻塞‌:所有耗时操作(网络请求、文件IO)必须放在子线程‌。
    • 内存泄漏‌:Handler 需使用弱引用或静态内部类,防止持有 Activity 引用‌。
    • 线程安全‌:多线程访问共享数据时需同步(如 volatileAtomic 类)‌。

    通过合理选择通信方式,可提升应用响应速度并降低ANR风险‌。

    6. 安卓进程间通信方式

    安卓进程间通信(IPC)方式详解

    一、常用通信方式
    1. Bundle + Intent

      • 原理‌:通过 Intent 携带 Bundle 对象传递数据,支持 Parcelable 或 Serializable 序列化,适用于四大组件间通信‌。
      • 特点‌:简单快捷,但仅支持单次单向数据传输,无法处理复杂场景‌。
    2. 文件共享

      • 原理‌:通过读写文件(如XML、JSON或普通文件)实现数据交换,需处理并发读写问题‌。
      • 适用场景‌:数据同步要求低、无需实时性的场景(如配置信息缓存)‌。
    3. Messenger

      • 原理‌:基于 Handler 和 AIDL 的轻量级通信,以消息队列传递 Message 对象,支持跨进程单向异步通信‌。
      • 特点‌:简化了 AIDL 的使用,但仅支持串行处理请求,不适合高并发‌。
    4. AIDL(Android接口定义语言)

      • 原理‌:通过定义跨进程接口实现方法调用,自动生成代理类处理通信细节,支持多线程和同步/异步操作‌。
      • 适用场景‌:需要高性能、复杂数据交互的服务调用(如远程音乐播放控制)‌。
    5. ContentProvider

      • 原理‌:封装数据并提供标准 CRUD 接口,通过 Uri 标识数据源,支持跨应用数据共享(如读取系统通讯录)‌。
      • 特点‌:数据访问权限可控,适合结构化数据共享‌。
    6. Binder

      • 原理‌:基于 C/S 架构的内核级通信机制,通过一次数据拷贝实现高效传输,支持身份验证和引用计数管理‌。
      • 特点‌:Android 核心 IPC 方案,AIDLMessenger 等均基于其实现‌。
    7. Socket(套接字)

      • 原理‌:基于网络协议(如TCP/IP)实现跨设备或本机进程通信,需处理连接管理和数据流解析‌。
      • 适用场景‌:网络通信或对传输效率要求不高的本地进程交互‌。

    二、特殊场景通信方式
    1. BroadcastReceiver

      • 原理‌:通过广播发送 Intent 实现一对多通信,支持有序广播和粘性广播,适用于系统级事件通知(如网络状态变化)‌。
      • 限制‌:数据量小(受 Intent 大小限制),实时性较低‌。
    2. 共享内存

      • 原理‌:通过 MemoryFile 或 Ashmem 共享内存区域,避免数据拷贝,适用于大数据量传输(如图像处理)‌。
      • 风险‌:需自行处理同步和内存泄漏问题‌。

    三、选型建议
    场景需求推荐方式优势
    简单数据传递(如启动组件)Bundle + Intent无需额外配置,开发成本低‌
    跨应用结构化数据共享ContentProvider标准化接口,权限可控‌
    远程服务调用(高并发)AIDL支持多线程和复杂数据类型‌
    单向异步通知(低并发)Messenger轻量级,代码简洁‌
    系统级事件广播BroadcastReceiver一对多通信,组件解耦‌
    高效大数据传输Binder / 共享内存减少拷贝次数,性能最优‌

    四、开发注意事项
    • 线程安全‌:AIDL 需手动处理多线程同步,避免并发冲突‌。
    • 内存泄漏‌:Binder 通信需及时注销监听器或释放资源‌。
    • 性能优化‌:避免在主线程执行耗时 IPC 操作(如大文件传输),防止 ANR‌。
    • 权限控制‌:跨进程访问敏感数据需声明权限(如 ContentProvider 的 read/write 权限)‌。

    通过合理选择 IPC 方式,可平衡性能、开发效率及安全性,满足不同业务场景需求‌。

    7. view的绘制流程

    Android View 绘制流程详解

    一、整体流程框架

    View 的绘制流程始于 ‌ViewRootImpl‌,通过 performTraversals() 方法依次触发 ‌测量(Measure)‌、‌布局(Layout)‌ 和 ‌绘制(Draw)‌ 三个阶段‌。

    • 触发时机‌:Activity 的 onResume() 完成后,ViewRootImpl 被创建并关联 DecorView(视图树的根节点)‌。
    • 递归逻辑‌:从根视图 DecorView 开始,逐层向下遍历所有子 View,最终完成整棵视图树的绘制‌。

    二、核心阶段分解
    1. 测量(Measure)

      • 触发入口‌:performTraversals() 调用 performMeasure(),执行根视图的测量逻辑‌。
      • 核心逻辑‌:
        • 父容器根据自身尺寸和子 View 的 LayoutParams 生成 ‌MeasureSpec‌(包含测量模式和尺寸),传递给子 View‌。
        • 子 View 的 onMeasure() 根据 MeasureSpec 计算自身宽高(通过 setMeasuredDimension() 保存结果)‌。
      • 关键类/方法‌:MeasureSpecView#onMeasure()ViewGroup#measureChildWithMargins()‌。
    2. 布局(Layout)

      • 触发入口‌:performTraversals() 调用 performLayout(),确定 View 在父容器中的位置‌。
      • 核心逻辑‌:
        • 父容器通过 layout() 设置自身位置,并调用子 View 的 layout() 传递位置参数(lefttoprightbottom)‌。
        • 子 View 在 onLayout() 中根据父容器分配的位置调整自身布局(如 ViewGroup 需计算子 View 的位置)‌。
    3. 绘制(Draw)

      • 触发入口‌:performTraversals() 调用 performDraw(),通过 draw() 方法完成绘制‌。
      • 核心逻辑‌:
        • 绘制顺序‌:背景 → 自身内容(onDraw()) → 子 View(dispatchDraw()) → 装饰(如滚动条)‌。
        • 绘制工具‌:通过 Canvas 和 Paint 对象进行图形绘制‌。

    三、关键数据结构与机制
    1. View 树结构

      • 根节点‌:DecorView(继承 FrameLayout),包含标题栏和内容区域(R.id.content)‌。
      • 递归遍历‌:父容器负责触发子 View 的绘制流程(如 ViewGroup 调用子 View 的 measure() 和 layout())‌。
    2. MeasureSpec 的作用

      • 组成‌:32 位整数,高 2 位表示测量模式(EXACTLYAT_MOSTUNSPECIFIED),低 30 位表示尺寸值‌。
      • 传递规则‌:父容器根据自身约束生成子 View 的 MeasureSpec,子 View 基于此计算实际尺寸‌。

    四、开发注意事项
    1. 性能优化

      • 避免在 onMeasure() 或 onDraw() 中执行耗时操作(如复杂计算或 IO 操作),防止主线程卡顿‌。
      • 使用 ViewStub 或动态加载减少视图层级复杂度‌。
    2. 自定义 View

      • 重写 onMeasure() 时必须调用 setMeasuredDimension() 保存测量结果,否则可能抛出异常‌。
      • 在 onDraw() 中避免频繁创建对象(如 Paint 或 Path),建议复用或提前初始化‌。

    通过理解并遵循上述流程,可高效实现复杂 UI 布局,同时规避性能瓶颈‌。

    8. 触摸事件的传递

    Android 触摸事件传递机制解析

    一、事件传递流程
    1. 起点:Activity → DecorView
      用户触摸屏幕后,事件首先由 ‌Activity‌ 的 dispatchTouchEvent() 接收,并传递至根视图 ‌DecorView‌(继承自 ViewGroup),作为事件分发的入口‌。

    2. ViewGroup → 子 View

      • 自上而下传递‌:父容器(如 ViewGroup)通过 dispatchTouchEvent() 向子 View 分发事件,若未拦截则逐级向下传递‌。
      • 拦截机制‌:父容器可通过 onInterceptTouchEvent() 拦截事件,强制由自身处理(返回 true 时停止向下传递)‌。
    3. 子 View 处理与事件回传

      • 若子 View 的 onTouchEvent() 返回 true(表示消费事件),事件传递终止;否则事件会向上回传至父容器,直至由 Activity 的 onTouchEvent() 处理‌。

    二、核心方法及作用
    1. dispatchTouchEvent(MotionEvent)

      • 入口方法‌:所有事件分发的起点,决定事件是否继续传递或终止‌。
      • 返回值逻辑‌:
        • true:事件被消费,停止传递;
        • false:未处理事件,回传给上层处理‌。
    2. onInterceptTouchEvent(MotionEvent)(仅 ViewGroup)

      • 拦截控制‌:在父容器中判断是否截获事件(如滑动冲突场景),默认返回 false‌。
    3. onTouchEvent(MotionEvent)

      • 最终消费‌:处理事件逻辑(如点击、滑动),返回 true 表示消费,终止传递链‌。

    三、关键特性与规则
    1. 事件消费优先级

      • OnTouchListener 优先于 onTouchEvent():若 View 设置了 OnTouchListener 且返回 true,则 onTouchEvent() 不会触发‌。
    2. ACTION_DOWN 的特殊性

      • 后续事件依赖‌:若 ACTION_DOWN 未被消费(所有 onTouchEvent() 返回 false),后续 MOVEUP 等事件将不再传递‌。
    3. 事件序列完整性

      • 同一事件序列(如 DOWN → MOVE → UP)应由同一 View 消费,避免中途切换处理者导致逻辑异常‌57。

    四、开发注意事项
    1. 避免过度拦截‌:频繁在 onInterceptTouchEvent() 中拦截事件可能导致子 View 无法响应正常操作(如点击失效)‌26。
    2. 性能优化‌:在 onTouchEvent() 中减少耗时操作,防止主线程卡顿‌58。
    3. 滑动冲突处理‌:通过父容器与子 View 的拦截协作(如 ScrollView 与 ListView)解决嵌套滑动问题‌26。

    通过理解上述机制,可精准控制事件分发路径,优化交互逻辑并解决复杂场景下的冲突问题‌15。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值