一. Messenger
-
要确保服务端进程处于存活状态,可以使用bindService拉起服务端进程
-
客户端binder对象传递到服务端,可通过service或者跳转参数携带(如Intent)
-
服务端给客户端发送消息,服务端拿到客户端binder后,创建一个客户端binder的Messenger对象,就可以给客户端发送消息
-
实现服务端的MessengerHandler
-
客户端给服务端发送消息,创建一个服务端的Messenger,通过Message中的replyTo给客户端
-
实现客户端MessengerHandler
public class MessengerService extends Service {
private static final String TAG = "MessagerService";
/**
* 处理来自客户端的消息,并用于构建Messenger
*/
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case Constant.MESSAGE_FROM_CLIENT:
Log.e(TAG, "receive message from client:" + message.getData().getString("msg"));
//获取客户端传递过来的Messenger,通过这个Messenger回传消息给客户端
Messenger client = message.replyTo;
//当然,回传消息还是要通过message
Message msg = Message.obtain(null, Constant.MESSAGE_FROM_SERVICE);
Bundle bundle = new Bundle();
bundle.putString("msg", "hello client, I have received your message!");
msg.setData(bundle);
try {
client.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(message);
break;
}
}
}
/**
* 构建Messenger对象
*/
private final Messenger mMessenger = new Messenger(new MessengerHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
//将Messenger对象的Binder返回给客户端
return mMessenger.getBinder();
}
}
/**
* 客户端Messenger对象
*/
private Messenger mClientMessenger = new Messenger(new MessengerHandler());
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.e(TAG, "ServiceConnection-->" + System.currentTimeMillis());
mService = new Messenger(iBinder);
Message message = Message.obtain(null, MESSAGE_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg", "hello service,this is client");
message.setData(bundle);
//将客户端的Messenger对象传递给服务端
message.replyTo = mClientMessenger;
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e(TAG, "onServiceDisconnected-->binder died");
}
};
/**
* 用于构建客户端的Messenger对象,并处理服务端的消息
*/
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case Constant.MESSAGE_FROM_SERVICE:
Log.e(TAG, "receive message from service:" + message.getData().getString("msg"));
break;
default:
super.handleMessage(message);
break;
}
}
}
二. AIDL
- 创建 AIDL 接口文件
首先在 src/main/aidl/com/example/service/ 目录下创建 IUserManager.aidl:
// IUserManager.aidl
package com.example.service;
// 定义用户数据类
parcelable UserData;
interface IUserManager {
// 添加用户
int addUser(in UserData user);
// 删除用户
boolean deleteUser(int userId);
// 获取用户列表
List<UserData> getUserList();
// 获取用户数量
int getUserCount();
// 注册回调监听器
void registerListener(IUserCallback callback);
// 注销回调监听器
void unregisterListener(IUserCallback callback);
}
在相同目录下创建 IUserCallback.aidl:
// IUserCallback.aidl
package com.example.service;
interface IUserCallback {
// 用户添加回调
void onUserAdded(in UserData user);
// 用户删除回调
void onUserDeleted(int userId);
// 用户数量变化回调
void onUserCountChanged(int count);
}
在相同目录下创建 UserData.aidl:
// UserData.aidl
package com.example.service;
parcelable UserData;
- 创建 UserData 数据类
// UserData.kt
package com.example.service
import android.os.Parcel
import android.os.Parcelable
data class UserData(
val userId: Int,
val userName: String,
val age: Int,
val email: String
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readInt(),
parcel.readString() ?: "",
parcel.readInt(),
parcel.readString() ?: ""
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(userId)
parcel.writeString(userName)
parcel.writeInt(age)
parcel.writeString(email)
}
override fun describeContents(): Int = 0
companion object CREATOR : Parcelable.Creator<UserData> {
override fun createFromParcel(parcel: Parcel): UserData {
return UserData(parcel)
}
override fun newArray(size: Int): Array<UserData?> {
return arrayOfNulls(size)
}
}
}
- 服务端实现
服务端 Service 实现:
// UserManagerService.kt
package com.example.server
import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.os.RemoteCallbackList
import android.os.RemoteException
import android.util.Log
import com.example.service.IUserManager
import com.example.service.IUserCallback
import com.example.service.UserData
class UserManagerService : Service() {
companion object {
private const val TAG = "UserManagerService"
}
// 用户数据存储
private val userList = mutableListOf<UserData>()
private var userIdCounter = 1
// 回调监听器列表(使用 RemoteCallbackList 自动处理进程死亡)
private val callbackList = RemoteCallbackList<IUserCallback>()
// Binder 实现
private val binder = object : IUserManager.Stub() {
@Throws(RemoteException::class)
override fun addUser(user: UserData): Int {
synchronized(userList) {
val newUser = user.copy(userId = userIdCounter++)
userList.add(newUser)
Log.d(TAG, "用户添加成功: ${newUser.userName}, ID: ${newUser.userId}")
// 通知所有监听器
notifyUserAdded(newUser)
notifyUserCountChanged(userList.size)
return newUser.userId
}
}
@Throws(RemoteException::class)
override fun deleteUser(userId: Int): Boolean {
synchronized(userList) {
val iterator = userList.iterator()
while (iterator.hasNext()) {
val user = iterator.next()
if (user.userId == userId) {
iterator.remove()
Log.d(TAG, "用户删除成功: $userId")
// 通知所有监听器
notifyUserDeleted(userId)
notifyUserCountChanged(userList.size)
return true
}
}
return false
}
}
@Throws(RemoteException::class)
override fun getUserList(): MutableList<UserData> {
synchronized(userList) {
return ArrayList(userList)
}
}
@Throws(RemoteException::class)
override fun getUserCount(): Int {
synchronized(userList) {
return userList.size
}
}
@Throws(RemoteException::class)
override fun registerListener(callback: IUserCallback) {
callbackList.register(callback)
Log.d(TAG, "监听器注册成功, 当前监听器数量: ${callbackList.registeredCallbackCount}")
}
@Throws(RemoteException::class)
override fun unregisterListener(callback: IUserCallback) {
callbackList.unregister(callback)
Log.d(TAG, "监听器注销成功, 当前监听器数量: ${callbackList.registeredCallbackCount}")
}
}
override fun onBind(intent: Intent): IBinder {
Log.d(TAG, "服务被绑定")
return binder
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "用户管理服务创建")
// 添加一些测试数据
addTestData()
}
override fun onDestroy() {
super.onDestroy()
callbackList.kill()
Log.d(TAG, "用户管理服务销毁")
}
private fun addTestData() {
val testUsers = listOf(
UserData(0, "张三", 25, "zhangsan@example.com"),
UserData(0, "李四", 30, "lisi@example.com")
)
testUsers.forEach { user ->
binder.addUser(user)
}
}
// 通知用户添加
private fun notifyUserAdded(user: UserData) {
val count = callbackList.beginBroadcast()
try {
for (i in 0 until count) {
try {
callbackList.getBroadcastItem(i).onUserAdded(user)
} catch (e: RemoteException) {
Log.e(TAG, "通知用户添加失败", e)
}
}
} finally {
callbackList.finishBroadcast()
}
}
// 通知用户删除
private fun notifyUserDeleted(userId: Int) {
val count = callbackList.beginBroadcast()
try {
for (i in 0 until count) {
try {
callbackList.getBroadcastItem(i).onUserDeleted(userId)
} catch (e: RemoteException) {
Log.e(TAG, "通知用户删除失败", e)
}
}
} finally {
callbackList.finishBroadcast()
}
}
// 通知用户数量变化
private fun notifyUserCountChanged(count: Int) {
val callbackCount = callbackList.beginBroadcast()
try {
for (i in 0 until callbackCount) {
try {
callbackList.getBroadcastItem(i).onUserCountChanged(count)
} catch (e: RemoteException) {
Log.e(TAG, "通知用户数量变化失败", e)
}
}
} finally {
callbackList.finishBroadcast()
}
}
}
服务端 AndroidManifest.xml 配置:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.server">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<service
android:name=".UserManagerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.service.USER_MANAGER_SERVICE" />
</intent-filter>
</service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
- 客户端实现
客户端 ServiceConnection:
// UserManagerClient.kt
package com.example.client
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import com.example.service.IUserManager
import com.example.service.IUserCallback
import com.example.service.UserData
class UserManagerClient(private val context: Context) {
companion object {
private const val TAG = "UserManagerClient"
private const val SERVICE_ACTION = "com.example.service.USER_MANAGER_SERVICE"
private const val SERVICE_PACKAGE = "com.example.server" // 服务端包名
}
private var userManager: IUserManager? = null
private var isServiceBound = false
// 回调监听器
private val userCallback = object : IUserCallback.Stub() {
@Throws(RemoteException::class)
override fun onUserAdded(user: UserData) {
Log.d(TAG, "回调: 用户添加 - ${user.userName} (ID: ${user.userId})")
// 在主线程更新UI
android.os.Handler(context.mainLooper).post {
onUserAddedCallback?.invoke(user)
}
}
@Throws(RemoteException::class)
override fun onUserDeleted(userId: Int) {
Log.d(TAG, "回调: 用户删除 - ID: $userId")
android.os.Handler(context.mainLooper).post {
onUserDeletedCallback?.invoke(userId)
}
}
@Throws(RemoteException::class)
override fun onUserCountChanged(count: Int) {
Log.d(TAG, "回调: 用户数量变化 - $count")
android.os.Handler(context.mainLooper).post {
onUserCountChangedCallback?.invoke(count)
}
}
}
// 客户端回调接口
var onUserAddedCallback: ((UserData) -> Unit)? = null
var onUserDeletedCallback: ((Int) -> Unit)? = null
var onUserCountChangedCallback: ((Int) -> Unit)? = null
// Service 连接
private val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
Log.d(TAG, "服务连接成功")
userManager = IUserManager.Stub.asInterface(service)
isServiceBound = true
// 注册回调监听器
try {
userManager?.registerListener(userCallback)
Log.d(TAG, "回调监听器注册成功")
} catch (e: RemoteException) {
Log.e(TAG, "注册回调监听器失败", e)
}
onConnectedCallback?.invoke()
}
override fun onServiceDisconnected(name: ComponentName?) {
Log.d(TAG, "服务连接断开")
isServiceBound = false
userManager = null
onDisconnectedCallback?.invoke()
}
}
var onConnectedCallback: (() -> Unit)? = null
var onDisconnectedCallback: (() -> Unit)? = null
// 绑定服务
fun bindService() {
Log.d(TAG, "开始绑定服务")
val intent = Intent(SERVICE_ACTION)
intent.`package` = SERVICE_PACKAGE // 设置包名确保找到正确服务
try {
val result = context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
if (!result) {
Log.e(TAG, "绑定服务失败")
}
} catch (e: Exception) {
Log.e(TAG, "绑定服务异常", e)
}
}
// 解绑服务
fun unbindService() {
if (isServiceBound) {
try {
userManager?.unregisterListener(userCallback)
} catch (e: RemoteException) {
Log.e(TAG, "注销回调监听器失败", e)
}
context.unbindService(serviceConnection)
isServiceBound = false
userManager = null
Log.d(TAG, "服务解绑成功")
}
}
// 添加用户
fun addUser(userName: String, age: Int, email: String): Int? {
if (!isServiceBound) {
Log.w(TAG, "服务未绑定,无法添加用户")
return null
}
return try {
val user = UserData(0, userName, age, email)
userManager?.addUser(user)
} catch (e: RemoteException) {
Log.e(TAG, "添加用户失败", e)
null
}
}
// 删除用户
fun deleteUser(userId: Int): Boolean {
if (!isServiceBound) {
Log.w(TAG, "服务未绑定,无法删除用户")
return false
}
return try {
userManager?.deleteUser(userId) ?: false
} catch (e: RemoteException) {
Log.e(TAG, "删除用户失败", e)
false
}
}
// 获取用户列表
fun getUserList(): List<UserData> {
if (!isServiceBound) {
Log.w(TAG, "服务未绑定,无法获取用户列表")
return emptyList()
}
return try {
userManager?.getUserList() ?: emptyList()
} catch (e: RemoteException) {
Log.e(TAG, "获取用户列表失败", e)
emptyList()
}
}
// 获取用户数量
fun getUserCount(): Int {
if (!isServiceBound) {
Log.w(TAG, "服务未绑定,无法获取用户数量")
return 0
}
return try {
userManager?.getUserCount() ?: 0
} catch (e: RemoteException) {
Log.e(TAG, "获取用户数量失败", e)
0
}
}
// 检查服务是否绑定
fun isBound(): Boolean = isServiceBound
}
客户端 Activity:
// MainActivity.kt
package com.example.client
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.service.UserData
class MainActivity : AppCompatActivity() {
private lateinit var userManagerClient: UserManagerClient
private lateinit var logTextView: TextView
private lateinit var userCountText: TextView
private lateinit var nameEditText: EditText
private lateinit var ageEditText: EditText
private lateinit var emailEditText: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initViews()
initUserManagerClient()
}
private fun initViews() {
logTextView = findViewById(R.id.log_text_view)
userCountText = findViewById(R.id.user_count_text)
nameEditText = findViewById(R.id.name_edit_text)
ageEditText = findViewById(R.id.age_edit_text)
emailEditText = findViewById(R.id.email_edit_text)
findViewById<Button>(R.id.bind_button).setOnClickListener { bindService() }
findViewById<Button>(R.id.unbind_button).setOnClickListener { unbindService() }
findViewById<Button>(R.id.add_user_button).setOnClickListener { addUser() }
findViewById<Button>(R.id.delete_last_button).setOnClickListener { deleteLastUser() }
findViewById<Button>(R.id.get_list_button).setOnClickListener { getUserList() }
findViewById<Button>(R.id.get_count_button).setOnClickListener { getUserCount() }
}
private fun initUserManagerClient() {
userManagerClient = UserManagerClient(this)
// 设置连接状态回调
userManagerClient.onConnectedCallback = {
runOnUiThread {
addLog("服务连接成功")
updateUserCount()
}
}
userManagerClient.onDisconnectedCallback = {
runOnUiThread {
addLog("服务连接断开")
userCountText.text = "服务未连接"
}
}
// 设置用户事件回调
userManagerClient.onUserAddedCallback = { user ->
addLog("回调: 用户添加 - ${user.userName} (ID: ${user.userId})")
updateUserCount()
}
userManagerClient.onUserDeletedCallback = { userId ->
addLog("回调: 用户删除 - ID: $userId")
updateUserCount()
}
userManagerClient.onUserCountChangedCallback = { count ->
addLog("回调: 用户数量变化 - $count")
updateUserCount()
}
}
private fun bindService() {
userManagerClient.bindService()
addLog("正在绑定服务...")
}
private fun unbindService() {
userManagerClient.unbindService()
addLog("服务已解绑")
}
private fun addUser() {
val name = nameEditText.text.toString().trim()
val ageText = ageEditText.text.toString().trim()
val email = emailEditText.text.toString().trim()
if (name.isEmpty() || ageText.isEmpty() || email.isEmpty()) {
Toast.makeText(this, "请填写完整用户信息", Toast.LENGTH_SHORT).show()
return
}
val age = ageText.toIntOrNull() ?: 0
if (age <= 0) {
Toast.makeText(this, "请输入有效的年龄", Toast.LENGTH_SHORT).show()
return
}
val userId = userManagerClient.addUser(name, age, email)
if (userId != null) {
addLog("添加用户成功: $name (ID: $userId)")
// 清空输入框
nameEditText.text.clear()
ageEditText.text.clear()
emailEditText.text.clear()
} else {
addLog("添加用户失败: 服务未连接")
}
}
private fun deleteLastUser() {
val userList = userManagerClient.getUserList()
if (userList.isNotEmpty()) {
val lastUser = userList.last()
val success = userManagerClient.deleteUser(lastUser.userId)
if (success) {
addLog("删除用户成功: ${lastUser.userName} (ID: ${lastUser.userId})")
} else {
addLog("删除用户失败")
}
} else {
addLog("没有用户可删除")
}
}
private fun getUserList() {
val userList = userManagerClient.getUserList()
addLog("当前用户列表:")
if (userList.isEmpty()) {
addLog(" 暂无用户")
} else {
userList.forEach { user ->
addLog(" ${user.userName} (ID: ${user.userId}, 年龄: ${user.age})")
}
}
}
private fun getUserCount() {
val count = userManagerClient.getUserCount()
addLog("当前用户数量: $count")
updateUserCount()
}
private fun updateUserCount() {
if (userManagerClient.isBound()) {
val count = userManagerClient.getUserCount()
userCountText.text = "用户数量: $count"
} else {
userCountText.text = "服务未连接"
}
}
private fun addLog(message: String) {
runOnUiThread {
val currentText = logTextView.text.toString()
val newText = if (currentText.isEmpty()) {
message
} else {
"$currentText\n$message"
}
logTextView.text = newText
}
}
override fun onDestroy() {
super.onDestroy()
userManagerClient.unbindService()
}
}
关键注意事项
- 跨进程数据传递
- 所有通过 AIDL 传递的数据必须实现 Parcelable 接口
- 基本数据类型、String、List、Map 等可以直接传递
- 回调监听器管理
- 使用 RemoteCallbackList 管理回调,自动处理进程死亡
- 回调方法会在 Binder 线程池中执行,需要切换到主线程更新 UI
- 异常处理
- 所有 AIDL 方法调用都要捕获 RemoteException
- 服务断开时要清理资源
- 服务绑定
- 使用明确的 Intent Action 和 Package 名称
- 及时在 onDestroy 中解绑服务
这个完整实例演示了 AIDL 通信的核心功能,包括:
· 基本数据操作(增删改查) · 回调监听机制 · 服务生命周期管理 · 异常处理 · 跨进程数据传递
可以根据需要扩展这个基础框架。
Android的AIDL(Android Interface Definition Language,安卓接口定义语言)是面试中跨进程通信部分的必考核心。下面我将从基础概念、工作原理、使用步骤、高级特性到面试题集,为你进行全面总结。
一、核心概念与要解决的问题
首先,理解AIDL的存在意义是关键,面试官常以此开场。
- 是什么:AIDL是一种IDL语言,用于定义跨进程通信的接口。它生成了一个Binder代理类的Java代码框架,开发者只需填充具体实现。
- 为什么需要:Android为每个应用分配独立的沙盒进程,内存不共享。当需要数据交互或能力调用时(如音乐App向系统服务请求音频焦点),就必须进行IPC。
- 与直接使用Binder的关系:AIDL是Binder的高级封装。手动实现Binder需要重写 onTransact 和 transact 方法,处理序列化等复杂细节;而AIDL自动生成了这些样板代码,让开发者聚焦业务逻辑。
二、AIDL的工作原理与通信流程
这是理解AIDL的基石。其核心是基于 Binder驱动 的 C/S 架构。
sequenceDiagram
participant Client
participant Stub_Proxy (AIDL生成)
participant Binder Driver
participant Stub (AIDL生成)
participant ServerImpl (开发者实现)
Note over Client, ServerImpl: 1. 建立连接
Client->>Stub_Proxy (AIDL生成): 绑定服务,获取Binder代理对象
Stub_Proxy (AIDL生成)-->>Client: 返回Proxy
Note over Client, ServerImpl: 2. 发起远程调用(以addBook为例)
Client->>Stub_Proxy (AIDL生成): 调用 addBook(book)
Stub_Proxy (AIDL生成)->>Stub_Proxy (AIDL生成): 1. 序列化参数(Parcel)
Stub_Proxy (AIDL生成)->>Binder Driver: 2. 调用 transact()
Binder Driver->>Stub (AIDL生成): 3. 路由到服务端 onTransact()
Stub (AIDL生成)->>Stub (AIDL生成): 4. 反序列化参数
Stub (AIDL生成)->>ServerImpl (开发者实现): 5. 调用实际 addBook() 方法
ServerImpl (开发者实现)->>ServerImpl (开发者实现): 6. 执行逻辑
ServerImpl (开发者实现)-->>Stub (AIDL生成): 7. 返回结果
Stub (AIDL生成)->>Stub (AIDL生成): 8. 序列化返回值(Parcel)
Stub (AIDL生成)-->>Binder Driver: 9. 返回结果
Binder Driver-->>Stub_Proxy (AIDL生成): 10. 返回结果
Stub_Proxy (AIDL生成)->>Stub_Proxy (AIDL生成): 11. 反序列化返回值
Stub_Proxy (AIDL生成)-->>Client: 12. 返回最终结果给调用者
理解上图中的两个核心角色:
- Proxy(代理):在客户端,由AIDL生成。它负责将调用打包(序列化)并通过Binder驱动发送出去。
- Stub(桩):在服务端,由AIDL生成并作为基类。它负责解包(反序列化)请求,并调用开发者编写的实际方法。
三、高级特性与核心机制(面试深入考察点)
这是区分你是否真正精通的关键。
定向Tag:in, out, inout
- in(默认):数据仅从客户端流向服务端。服务端修改参数,客户端对象不受影响。
- out:数据仅从服务端流回客户端。客户端传入的对象(字段初始值不重要),服务端可填充数据并传回。
- inout:双向流通。
- 原理:影响 Parcel 的序列化/反序列化流程。out 和 inout 会重新从Parcel中反序列化生成新对象并赋值回客户端参数。
- 性能建议:若无必要,优先使用 in,因为 out/inout 会触发额外的序列化开销。
oneway 关键字
- 用于修饰AIDL方法,如 oneway void doSomething();。
- 作用:使方法调用变为异步非阻塞。客户端调用后立即返回,无需等待服务端处理。
- 限制:不能有返回值,也不能声明 throws 异常。
线程模型与安全性
- 服务端方法执行线程:Binder线程池。默认情况下,你的服务端实现必须处理并发调用,确保线程安全。
- 客户端调用线程:如果从UI线程发起调用,会阻塞UI线程(同步调用)。因此,强烈建议在客户端将AIDL调用置于子线程。
异常处理
- 服务端抛出的 RemoteException 表示通信过程失败(如连接断开)。
- 服务端抛出的其他异常(如 SecurityException)会传递到客户端,但会重新包装。需要在AIDL接口方法上显式声明 throws。
死亡代理 (linkToDeath & unlinkToDeath)
- 客户端可以给Binder对象注册一个死亡代理,当服务端进程意外终止时,客户端能收到回调并进行重连等恢复操作。
四、典型面试问题与回答思路
- AIDL是什么?解决了什么问题?
- 思路:从Android进程沙盒机制引出IPC需求,说明AIDL是用于定义IPC接口的IDL,它能自动生成Binder通信的复杂模板代码。
- 简述一次AIDL调用的完整流程。
- 思路:按照【工作原理】部分的流程图,清晰描述从客户端Proxy序列化,经Binder驱动,到服务端Stub反序列化并执行,再原路返回的过程。
- AIDL支持哪些数据类型?
- 思路:分两类回答。基本类型:Java所有基本类型(如int、long)、String、CharSequence、List/Map(其内元素也须支持)。特殊类型:实现 Parcelable 的对象、其他AIDL接口、IBinder。
- 定向Tag in, out, inout 有什么区别?
- 思路:从数据流向和性能开销两方面对比。强调默认是 in,以及 out/inout 会引发额外的反序列化操作。
- oneway 关键字有什么用?
- 思路:声明它为异步非阻塞调用。立刻回答其限制:不能有返回值,不能抛出异常。
- AIDL调用是同步还是异步?会阻塞UI线程吗?
- 思路:明确指出默认是同步的。如果客户端在UI线程调用,就会阻塞UI线程。因此最佳实践是在后台线程进行AIDL调用。
- 服务端执行AIDL方法在什么线程?需要注意什么?
- 思路:在Binder线程池中执行。必须注意多线程并发安全问题,对共享数据的访问要加锁或使用并发容器。
- 如何传递一个自定义类型(如Book)?
- 思路:必须让该类实现 Parcelable 接口,并详细说明步骤:
- 实现接口;
- 编写 writeToParcel 和 describeContents;
- 添加静态 CREATOR 字段;
- 在AIDL文件中声明。
- 客户端如何感知服务端进程死亡?
- 思路:通过 linkToDeath 注册死亡代理。当服务端进程终止,客户端的 DeathRecipient 回调会被触发,可在其中进行重连或清理。
- AIDL和Messenger、ContentProvider在IPC场景下如何选择?
- 思路:这是架构题。AIDL:适用于方法调用复杂、需要高并发、有同步返回的场景。Messenger:基于AIDL封装,适用于简单的消息队列式通信,底层串行处理。ContentProvider:主要用于数据共享,提供CRUD接口。