1.四大组件
Android 的四大核心组件是应用开发的基础框架,它们各自承担独特职责并通过系统协同工作:
Activity(活动)
- 作用:用户交互的界面载体,如一个屏幕页面(例如微信聊天窗口、购物APP商品页)。
- 特点:管理生命周期(
onCreate()
, onResume()
等),通过Intent
启动其他组件。
- 示例:登录界面、主菜单页面。
Service(服务)
- 作用:后台执行长时间任务(无界面),如下载文件、播放音乐。
- 类型:
Started Service
(启动后独立运行)
Bound Service
(被其他组件绑定调用)
- 注意:主线程运行,需开子线程防卡顿。
Broadcast Receiver(广播接收器)
- 作用:监听系统/应用广播事件(如电量不足、网络变化),并触发响应。
- 使用方式:
- 静态注册(
AndroidManifest.xml
声明,常驻监听)
- 动态注册(代码中注册,灵活控制生命周期)
- 示例:监听开机完成事件、自定义应用消息推送。
Content Provider(内容提供者)
- 作用:跨应用共享数据的标准化接口(如通讯录、相册访问)。
- 机制:通过
URI
标识数据源,配合ContentResolver
操作(增删改查)。
- 安全:需在
AndroidManifest.xml
声明权限控制访问。
🛠 关键共同点
- 必须声明:所有组件需在
AndroidManifest.xml
中注册。
- 启动方式:通过
Intent
(隐式/显式)激活组件(Content Provider 通过ContentResolver
)。
- 生命周期:每个组件有独立生命周期回调方法需覆写。
组件间关系示例
1 2 3 4 5
| graph LR A[Activity] -->|启动| B(Service) A -->|发送| C[Broadcast] C -->|接收| D[Broadcast Receiver] A -->|查询| E[Content Provider]
|
1.1.Activity
1.1.1.启停活动页面
- Activity的启动与结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class ActStartActivity extends AppCompatActivity implements View.OnClickListener {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_act_start); findViewById(R.id.btn_act_content).setOnClickListener(this); }
@Override public void onClick(View view) { startActivity(new Intent(this, ActFinishActivity.class)); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ActFinishActivity extends AppCompatActivity implements View.OnClickListener {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_act_finish); findViewById(R.id.iv_back).setOnClickListener(this); findViewById(R.id.btn_finish).setOnClickListener(this); }
@Override public void onClick(View view) { if (view.getId() == R.id.iv_back || view.getId() == R.id.btn_finish){ finish(); } } }
|
- Activity的生命周期

- onCreate:创建活动。把页面布局加载进内存,进入初始状态。
- onStart:开始活动。把活动页面显示在屏幕上,进入了就绪状态。
- onResume:恢复活动。活动页面进入活跃状态,能够与用户正常交互,例如允许响应用户的点击动作、允许用户输入文字等。
- onPause:暂停活动。活动页面进入暂停状态,无法与用户正常交互。
- onStop:停止活动。页面将不在显示上屏幕。
- onDestroy:销毁活动。回收活动占用的系统资源,把页面从内存中清除。
- onNewIntent:重用已有的活动实例。
Activity的启动模式
- standard,标准的出栈入栈,不复用。
- singleTop,当启动的Activity,在栈顶有相同的Activity时,直接复用这个Activity,而不会再增加一个入栈的Activity。
- singleTask,当启动的Activity,在当前栈中已经有相同的Activity时,哪怕是在底部,也会将上面的其他Activity全部弹出,然后再将该Activity入栈复用。
- singleInstance,当启动的Activity,栈中已经有其他的Activity时会新建一个栈,然后将当前的Activity加入到新栈中。也就是全局唯一模式,一般应用于主页。
设置启动模式
1 2 3 4 5
| Intent intent = new Intent(this, LoginSuccessActivity.class)
intent.setFlags(Intnet.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
|
1.1.2.在活动之前传递消息
- 显示和隐式Intent
1
| startActivity(new Intent(this, ActFinishActivity.class));
|

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
| @Override public void onClick(View view) { String phoneNumber = "12345"; Intent intent = new Intent(); if (view.getId() == R.id.btn_dial) { intent.setAction(Intent.ACTION_DIAL); Uri uri = Uri.parse("tel:" + phoneNumber); intent.setData(uri); startActivity(intent); } else if (view.getId() == R.id.btn_sms) { intent.setAction(Intent.ACTION_SENDTO); Uri uri = Uri.parse("smsto:" + phoneNumber); intent.setData(uri); startActivity(intent); } else if (view.getId() == R.id.btn_my) { intent.setAction("android.intent.action.NING"); intent.addCategory(Intent.CATEGORY_DEFAULT); startActivity(intent); } } }
|

- 向下一个Activity发送数据
1 2 3 4 5 6 7 8 9 10 11 12
| @Override public void onClick(View view) { Intent intent = new Intent(this, ActReceiveActivity.class); Bundle bundle = new Bundle(); bundle.putString("request_time", "18 06 2025"); bundle.putString("request_content", tv_send.getText().toString()); intent.putExtras(bundle); startActivity(intent);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_act_receive); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); tv_receive = findViewById(R.id.tv_receive); Bundle bundle = getIntent().getExtras(); assert bundle != null; String requestTime = bundle.getString("request_time"); String requestContent = bundle.getString("request_content"); String formatData = String.format("receive request message: \nthe time is: %s\nthe request content is: %s\n", requestTime, requestContent); tv_receive.setText(formatData);
}
|
- 向上一个Activity返回数据
1.1.3.为活动补充附加信息
- 利用资源文件配置字符串
1 2 3 4 5
| <resources> <string name="app_name">chaper04</string> <string name="title_activity_act_finish">ActFinishActivity</string> <string name="weather_str">sunny day</string> </resources>
|
- 在java文件中可以通过getString方法获取这个字符串
1
| String value = getString(R.String.weather_str);
|
- 利用元数据传递配置信息
1 2 3 4 5 6 7 8 9
| <activity android:name=".ActSendActivity" android:exported="true" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="api_token" android:value="SNA341FS5E12JAN34AS613YKKSJN"/> </activity>
|
1 2 3 4 5 6 7
| PackageManager pm = getPackageManager();
pm.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
Bundle bundle = info.metaData; bundle.getString("api_token");
|
1.2.数据存储
1.2.1.共享参数SharedPreferences
- SharedPreferences是一个轻量级存储工具。
- 采用key-value存储形式
- 使用xml文件格式存储
- 关闭程序不清空数据
- 一些记住密码功能可能会将密码存储到SharedProferences中。

- 共享参数用法
1 2 3 4 5 6 7 8
| SharedPreferences preference = getSharedPreferences("config", Context.MODE_PRIVATE); SharedPreferences.Editor edit = preference.edit(); String name = "anny"; int age = 15; edit.putString("name", name); edit.putInt("age", age); edit.commit();
|
保存位置

1
| String value = preference.getString("name", null);
|
1.2.2.数据库SQLite
SQL的基本语法
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
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_database_create" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="create database" android:textColor="@color/black" android:textSize="17sp"/> <Button android:id="@+id/btn_database_delete" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="delete database" android:textColor="@color/black" android:textSize="17sp"/>
</LinearLayout> <TextView android:id="@+id/tv_database" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="5dp" android:textColor="@color/black" android:textSize="17sp"/>
</LinearLayout>
|
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 49 50 51 52
| package com.gaomu.chapter06;
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.view.View; import android.widget.TextView;
import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat;
public class DatabaseActivity extends AppCompatActivity implements View.OnClickListener {
private TextView tv_database; private String mDatabasePath;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_database); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); tv_database = findViewById(R.id.tv_database); findViewById(R.id.btn_database_create).setOnClickListener(this); findViewById(R.id.btn_database_delete).setOnClickListener(this); mDatabasePath = getFilesDir() + "/test.db";
}
@Override public void onClick(View view) { if (view.getId() == R.id.btn_database_create) { SQLiteDatabase db = openOrCreateDatabase(mDatabasePath, Context.MODE_PRIVATE, null); String desc = String.format("数据库%s创建%s", db.getPath(), "成功"); tv_database.setText(desc); } else if (view.getId() == R.id.btn_database_delete) { boolean result = deleteDatabase(mDatabasePath); String desc = String.format("数据库%s删除%s", mDatabasePath, result ? "成功" : "失败"); tv_database.setText(desc); } } }
|


数据库管理器SQLiteDatabase
常用API接口
openDatabase: 打开指定路径的数据库
isOpen: 判断数据库是否打开
close:关闭数据库。
getVersion:获取数据库版本号
setVersion:设置数据库的版本号
数据处理
execSQL:执行拼接号的SQL控制语句。
delete:删除符合条件的记录
update:更新符合条件的记录
query:执行查询操作,返回结果集的游标
rawQuery:执行拼接号的SQL查询语句,返回结果集的游标。
数据库帮助器SQLLiteOpenHelper
对数据库中的数据进行操作需要用到SQLLiteOpenHelper,
使用继承SQLLiteOpenHelper的数据库操作类,提示重写onCreate和onUpgrade两个方法。
优化记住密码功能
1.2.3.存储卡的文件操作
私有存储空间于公共存储空间
在存储卡上读写文本文件
在存储卡上读写图片文件
1.2.4.应用组件Application
- 在App运行的整个过程中有且仅有一个Application。
- Application比Activity新启动,且比Activity后关闭。(现有页面采用应用)
Applicaiton可以编写
1 2 3 4 5 6 7 8 9
| <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:name=".MyApplication" ... </application>
</manifest>
|
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
| package com.gaomu.chapter06;
import android.app.Application; import android.content.res.Configuration; import android.util.Log;
import androidx.annotation.NonNull;
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Log.d("ning", "MyApplication start"); }
@Override public void onTerminate() { super.onTerminate(); Log.d("ning", "App close");
}
@Override public void onConfigurationChanged(@NonNull Configuration newConfig){ super.onConfigurationChanged(newConfig); Log.d("ning", "onConfigurationChanged"); } }
|
Application的生命周期
利用Application操作全局变量
利用Room简化数据库操作
- 编写是实体类,该类添加@Entity注解
- 添加持久化类,@Dao注解
- 编写数据库类,该类从RoomDatabase派生而来,继承该类,并添加@Database注解,声明抽象的Dao。
- 在自定义的Application类中声明数据库的唯一实例
- 在操作信息表的地方获取数据库的持久化对象
1.3.内容提供者
- ContentProvider为App存取内部数据提供了统一的外部接口。
1.3.1.在应用之间共享数据
通过ContentProvider封装数据
URi结构,代表数据操作地址
content://authority/data_path/id
content:// 通用前缀
authority 授权名称,标识具体哪一个ContentProvider提供资源
data_path 是数据路径,用来确定请求的是那个数据集
id 数据编号,标识单条数据
通过ContentResolver访问数据

- 出于安全考虑,Android11要求应用事先说明需要访问的其他软件包
1 2 3 4
| <queries> <package android:name="com.gaomu.apkserver"/> <provider android:authorities="com.gaomu.apkserver.provider.UserInfoProvider" </queries>
|
1.3.2.在内容组件获取通讯信息
运行时动态申请权限
利用ContentResolver读写联系人
利用ContentObserver监听短信
1.3.3.在应用之间共享文件
使用相册发送彩信
借助FileProvider发送彩信
借助FileProvider安装应用
1.4.安卓打包发布
1.4.1.默认测试时,会在构建目录下生成测试版本的APK文件

1.4.2.打包生产环境的APK







