1. 事件监听(Event Listener) vs 回调(Callback)
定义
• 事件监听:通过接口(如 OnClickListener
)监听特定 UI 组件的用户交互事件(如点击)。
• 回调:系统或框架在特定生命周期或异步操作完成后调用的方法(如 onCreate()
)。
关键区别
特性 | 事件监听 | 回调 |
---|---|---|
触发条件 | 用户交互(如点击、滑动) | 系统生命周期或异步任务完成 |
实现方式 | 实现特定接口(如 OnClickListener ) | 重写方法(如 onCreate() ) |
作用范围 | 针对单个组件 | 通常关联组件或全局生命周期 |
代码示例
// 事件监听:按钮点击
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 处理点击事件
}
});
// 回调:Activity 的 onCreate 方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
2. 显式 Intent(Explicit Intent) vs 隐式 Intent(Implicit Intent)
定义
• 显式 Intent:明确指定目标组件(如 Activity 或 Service),用于应用内部跳转。
• 隐式 Intent:通过动作(Action)、数据类型(Data)等描述操作,由系统匹配处理组件。
关键区别
特性 | 显式 Intent | 隐式 Intent |
---|---|---|
目标组件 | 明确指定(如 SecondActivity.class ) | 不指定,由系统匹配 |
用途 | 应用内部跳转 | 跨应用调用(如打开网页、分享) |
安全性 | 高(直接指定目标) | 低(需验证是否有组件处理该 Intent) |
代码示例
// 显式 Intent:启动 SecondActivity
Intent explicitIntent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(explicitIntent);
// 隐式 Intent:打开网页
Intent implicitIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com"));
if (implicitIntent.resolveActivity(getPackageManager()) != null) {
startActivity(implicitIntent);
}
3. Service vs Thread
定义
• Service:Android 组件,用于在后台执行长时间任务,无 UI,默认在主线程运行。
• Thread:Java 线程,用于执行异步任务,需手动管理生命周期。
关键区别
特性 | Service | Thread |
---|---|---|
生命周期 | 由系统管理,可绑定(bind)或启动(start) | 手动管理 |
运行线程 | 默认主线程,需手动创建子线程 | 直接在新线程运行 |
用途 | 后台音乐播放、网络请求等 | 异步任务(如计算密集型操作) |
代码示例
// Service 示例(需在 AndroidManifest.xml 中声明)
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 执行任务(需手动创建子线程)
new Thread(() -> {
// 后台操作
}).start();
return START_STICKY;
}
}
// Thread 示例
new Thread(() -> {
// 异步任务
}).start();
4. Fragment vs Activity
定义
• Fragment:代表部分 UI,可嵌入 Activity 中,有独立生命周期。
• Activity:代表单个屏幕,管理用户交互和全局生命周期。
关键区别
特性 | Fragment | Activity |
---|---|---|
生命周期 | 依赖宿主 Activity | 独立生命周期 |
复用性 | 高(可多 Activity 复用) | 低(通常单独使用) |
UI 管理 | 管理部分 UI | 管理全局 UI |
代码示例
// Activity 中加载 Fragment
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, new MyFragment())
.commit();
// Fragment 生命周期方法示例
public class MyFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
// 初始化 UI
}
}
5. BroadcastReceiver(全局广播) vs LocalBroadcastManager(本地广播)
定义
• BroadcastReceiver:监听系统或应用全局广播(如网络状态变化)。
• LocalBroadcastManager:仅在应用内部发送和接收广播,更高效安全。
关键区别
特性 | BroadcastReceiver | LocalBroadcastManager |
---|---|---|
作用范围 | 全局(跨应用) | 应用内 |
安全性 | 低(可能被其他应用接收) | 高(仅限应用内部) |
性能 | 低(跨进程通信) | 高(无需跨进程) |
代码示例
// 全局广播注册(AndroidManifest.xml 或动态注册)
IntentFilter filter = new IntentFilter("com.example.MY_ACTION");
registerReceiver(receiver, filter);
// 本地广播发送
LocalBroadcastManager.getInstance(this)
.sendBroadcast(new Intent("com.example.LOCAL_ACTION"));
6. AsyncTask vs Handler/Thread
定义
• AsyncTask:简化异步任务的工具类(已弃用),封装了 Thread
和 Handler
,适合短时间任务(如网络请求)。
• Handler/Thread:手动管理线程和消息循环,适合复杂异步操作。
关键区别
特性 | AsyncTask | Handler/Thread |
---|---|---|
生命周期 | 与 Activity 绑定,容易内存泄漏 | 需手动管理,灵活性高 |
线程切换 | 自动切换主线程更新 UI | 需通过 Handler.post() 手动切换 |
适用场景 | 简单异步任务(已弃用,推荐用协程/RxJava) | 复杂异步任务或需精细控制线程时 |
代码示例
// AsyncTask(已弃用,仅作参考)
class MyAsyncTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... voids) {
return "Result";
}
@Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
// Handler/Thread
Handler handler = new Handler(Looper.getMainLooper());
new Thread(() -> {
String result = doWork();
handler.post(() -> textView.setText(result));
}).start();
7. SharedPreferences vs SQLite
定义
• SharedPreferences:键值对存储,用于保存简单数据(如用户设置)。
• SQLite:关系型数据库,适合结构化数据存储(如用户订单)。
关键区别
特性 | SharedPreferences | SQLite |
---|---|---|
数据类型 | 基本类型(String、Int 等) | 结构化数据(表、行、列) |
查询能力 | 无查询语法,直接读写键值对 | 支持 SQL 复杂查询(JOIN、WHERE 等) |
性能 | 适合少量数据 | 适合大数据量和高频读写 |
代码示例
// SharedPreferences 示例
SharedPreferences prefs = getSharedPreferences("my_prefs", MODE_PRIVATE);
prefs.edit().putString("username", "Alice").apply();
String username = prefs.getString("username", "");
// SQLite 示例(使用 Room 简化)
@Dao
public interface UserDao {
@Query("SELECT * FROM user WHERE id = :userId")
User getUserById(int userId);
}
8. RecyclerView vs ListView
定义
• RecyclerView:更灵活、高性能的列表控件,强制使用 ViewHolder 模式。
• ListView:旧版列表控件,简单但性能较差。
关键区别
特性 | RecyclerView | ListView |
---|---|---|
布局管理 | 支持多种布局(线性、网格、瀑布流) | 仅支持垂直列表 |
动画支持 | 内置 Item 动画支持 | 需手动实现 |
复用机制 | 更高效的 View 复用 | 基础复用,性能较低 |
代码示例
// RecyclerView 示例(需 Adapter 和 ViewHolder)
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new MyAdapter(dataList));
// ListView 示例
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, dataArray));
9. PendingIntent vs Intent
定义
• Intent:用于组件间通信(如启动 Activity)。
• PendingIntent:允许外部应用以当前应用权限执行某个 Intent(如通知点击)。
关键区别
特性 | Intent | PendingIntent |
---|---|---|
执行主体 | 直接由当前应用触发 | 可由其他应用或系统触发 |
典型用途 | 应用内部跳转 | 通知、AlarmManager、App Widget |
权限 | 无额外权限 | 需声明权限(如发送通知) |
代码示例
// Intent 示例
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
// PendingIntent 示例(用于通知)
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, intent, PendingIntent.FLAG_IMMUTABLE
);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channel_id")
.setContentIntent(pendingIntent);
10. Toast vs Snackbar
定义
• Toast:短暂的非侵入式消息提示,不干扰用户操作。
• Snackbar:Material Design 风格的提示,可包含交互按钮。
关键区别
特性 | Toast | Snackbar |
---|---|---|
交互性 | 无按钮 | 可添加操作按钮(如 “Undo”) |
显示位置 | 默认屏幕底部 | 可嵌入到特定 View 下方 |
设计规范 | 无 Material Design 约束 | 遵循 Material Design 规范 |
代码示例
// Toast 示例
Toast.makeText(this, "Message sent", Toast.LENGTH_SHORT).show();
// Snackbar 示例
Snackbar.make(rootView, "File deleted", Snackbar.LENGTH_LONG)
.setAction("Undo", v -> restoreFile())
.show();
11. ContentProvider vs File 存储
定义
• ContentProvider:跨应用数据共享的标准化接口(如通讯录数据)。
• File 存储:直接读写应用私有文件或公共存储(如 SD 卡)。
关键区别
特性 | ContentProvider | File 存储 |
---|---|---|
数据共享 | 支持跨应用访问 | 仅限当前应用或申请权限访问公共文件 |
安全性 | 通过 URI 权限控制 | 依赖文件系统权限 |
使用场景 | 暴露结构化数据给其他应用 | 内部文件缓存或无需共享的数据 |
代码示例
// ContentProvider 查询(如获取通讯录)
Cursor cursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI,
null, null, null, null
);
// File 存储示例(写入私有文件)
File file = new File(getFilesDir(), "data.txt");
try (FileOutputStream fos = openFileOutput("data.txt", MODE_PRIVATE)) {
fos.write("Hello".getBytes());
}
12. ViewModel vs SavedState
定义
• ViewModel:在配置变更(如屏幕旋转)后保留数据。
• SavedState:在进程被系统杀死后恢复数据(如返回栈中的 Activity)。
关键区别
特性 | ViewModel | SavedState |
---|---|---|
数据保留范围 | 配置变更(如旋转屏幕) | 进程死亡后恢复 |
实现方式 | 通过 ViewModel 类 | 通过 onSaveInstanceState(Bundle) |
数据类型 | 复杂对象(如网络请求结果) | 简单类型(String、Int 等) |
代码示例
// ViewModel 示例
public class MyViewModel extends ViewModel {
private MutableLiveData<String> data = new MutableLiveData<>();
// 逻辑代码...
}
// SavedState 示例
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("key", "value");
super.onSaveInstanceState(outState);
}
13. 安装来源:应用商店 vs 未知来源(Unknown Sources)
定义
• 应用商店安装:通过 Google Play 等受信任渠道安装,自动验证签名和权限。
• 未知来源安装:用户手动安装 APK(需开启「未知来源」设置),存在安全风险。
关键区别
特性 | 应用商店安装 | 未知来源安装 |
---|---|---|
签名验证 | 强制验证应用签名 | 无自动验证(依赖用户判断) |
权限管理 | 安装时提示权限 | 安装时不提示权限,运行时动态申请 |
系统限制 | 无额外限制 | 需用户手动开启「安装未知应用」权限 |
代码示例(检测未知来源安装)
// 检查应用是否来自 Play Store(仅供参考,非 100% 可靠)
public boolean isInstalledFromPlayStore() {
String installerPackage = getPackageManager().getInstallerPackageName(getPackageName());
return "com.android.vending".equals(installerPackage);
}
14. 签名权限(Signature Permission) vs 普通权限(Normal Permission)
定义
• 签名权限:只有与声明权限的应用使用相同签名的应用才能获得。
• 普通权限:任何应用均可申请,需用户授权(如 INTERNET
)。
关键区别
特性 | 签名权限 | 普通权限 |
---|---|---|
授权方式 | 自动授予(相同签名) | 需用户动态授权 |
安全级别 | 高(限制跨应用访问) | 低(用户可控) |
典型用途 | 内部组件通信(如私有 ContentProvider) | 基础功能(网络、存储等) |
代码示例(声明签名权限)
<!-- AndroidManifest.xml -->
<permission
android:name="com.example.MY_PRIVATE_PERMISSION"
android:protectionLevel="signature" />
<!-- 使用权限 -->
<uses-permission android:name="com.example.MY_PRIVATE_PERMISSION" />
15. 有序广播(Ordered Broadcast) vs 普通广播(Normal Broadcast)
定义
• 有序广播:按优先级顺序发送,可被中途拦截或修改(如短信广播)。
• 普通广播:异步发送给所有接收者,无法拦截或修改。
关键区别
特性 | 有序广播 | 普通广播 |
---|---|---|
传递顺序 | 按优先级顺序传递 | 同时发送给所有接收者 |
可拦截性 | 支持 abortBroadcast() 中止广播 | 不可中止 |
数据修改 | 接收者可修改 Intent 数据 | 数据不可修改 |
代码示例(发送有序广播)
// 发送有序广播
Intent intent = new Intent("com.example.ORDERED_ACTION");
sendOrderedBroadcast(intent, null);
// 接收者设置优先级
<receiver android:name=".MyReceiver">
<intent-filter android:priority="100">
<action android:name="com.example.ORDERED_ACTION" />
</intent-filter>
</receiver>
16. 动态注册广播 vs 静态注册广播
定义
• 动态注册:通过代码注册广播接收器(如 registerReceiver()
),生命周期与组件绑定。
• 静态注册:在 AndroidManifest.xml
中声明,应用未启动时也能接收(如开机广播)。
关键区别
特性 | 动态注册广播 | 静态注册广播 |
---|---|---|
生命周期 | 随组件销毁自动注销 | 持久化(直到应用卸载) |
接收场景 | 应用运行时生效 | 应用未运行时可接收(系统广播) |
系统限制 | 无限制 | Android 8.0+ 限制部分隐式静态广播 |
代码示例(动态注册广播)
// 注册
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 处理广播
}
};
IntentFilter filter = new IntentFilter("com.example.DYNAMIC_ACTION");
registerReceiver(receiver, filter);
// 注销(通常在 onDestroy 中)
unregisterReceiver(receiver);
17. 应用沙箱(App Sandbox) vs SELinux
定义
• 应用沙箱:每个应用在独立 Linux 用户 ID 下运行,隔离文件和数据。
• SELinux:强制访问控制(MAC)系统,限制进程和文件的权限。
关键区别
特性 | 应用沙箱 | SELinux |
---|---|---|
隔离机制 | 基于 Linux 用户 ID | 基于安全策略(Policy) |
控制粒度 | 进程级别隔离 | 文件、进程、网络等细粒度控制 |
开发者影响 | 自动生效,无需配置 | 系统厂商定制策略,开发者通常不直接修改 |
18. KeyStore vs SharedPreferences 存储敏感数据
定义
• KeyStore:安全存储加密密钥和证书的系统级 API。
• SharedPreferences:存储简单数据,明文不安全。
关键区别
特性 | KeyStore | SharedPreferences |
---|---|---|
安全性 | 高(硬件支持密钥保护) | 低(明文存储) |
数据类型 | 密钥、证书 | 字符串、整型等基本类型 |
典型用途 | 加密用户敏感数据 | 保存非敏感配置信息 |
代码示例(使用 KeyStore 存储密钥)
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"
);
keyGenerator.init(new KeyGenParameterSpec.Builder(
"my_key",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
19. ContentProvider 的 android:exported
vs android:permission
定义
• android:exported
:控制 ContentProvider 是否允许其他应用访问。
• android:permission
:设置访问 ContentProvider 所需的权限。
关键区别
特性 | android:exported | android:permission |
---|---|---|
作用范围 | 全局开关(允许/禁止跨应用访问) | 细粒度权限控制 |
默认值 | 如果包含 <intent-filter> 则默认 true | 默认无权限要求 |
优先级 | 先判断 exported,再验证 permission | 需在 exported=true 时生效 |
代码示例(安全配置 ContentProvider)
<provider
android:name=".MyContentProvider"
android:authorities="com.example.provider"
android:exported="false" <!-- 仅限内部使用 -->
android:permission="com.example.READ_PERMISSION" <!-- 跨应用时设置权限 -->
/>