Android四大组件

Android 的四大组件指:Activity Service Broadcast ContentProvider
图片

Android四大组件

Activity

生命周期

生命周期:onCreate() -> onStart() - > onResume() -> onPause() -> onStop() -> onDestroy()

当跳转到新活动时,Activity的生命周期为onCreate() -> onStart() - > onResume()

当锁屏或跳转到新活动时,Activity会调用onPause()方法,从锁屏或者其他活动返回时,Activity会调用onResume()方法,再次进入运行状态

当APP退到后台,但不退出时,Activity会调用onPause() -> onStop()方法,再次回到APP时会调用onRestart -> onStart() - > onResume()

onCreate

在该onCreate() 方法中,您将执行基本应用程序启动逻辑,该逻辑应该在活动的整个生命周期中仅发生一次。例如,您的实现可能会将数据绑定到列表,将活动与a关联 ,并实例化一些类范围变量。此方法接收参数,该参数是 包含活动先前保存状态的对象。如果活动以前从未存在过,则对象的值为null。

onStart

当活动进入Started状态时,系统将调用此回调。该onStart()调用使活动对用户可见,因为应用程序准备活动以进入前台并变为交互式。例如,此方法是应用程序初始化维护UI的代码的位置。

onResume

活动进入Resumed状态时,它进入前台,然后系统调用onResume() 回调。这是应用程序与用户交互的状态。该应用程序保持这种状态,直到某些事情成为焦点远离应用程序。例如,这样的事件可能是接收电话,用户导航到另一个活动,或者设备屏幕关闭。

onPause

系统将此方法称为用户离开您的活动的第一个指示(尽管并不总是意味着活动正在被销毁); 它表示活动不再在前台(尽管如果用户处于多窗口模式,它仍然可见)。使用该onPause()方法暂停或调整Activity在处于暂停状态时不应继续(或应继续适度)的操作,并且您希望很快恢复。

onStop

当您的活动不再对用户可见时,它已进入 Stopped状态,系统将调用 onStop()回调。例如,当新启动的活动覆盖整个屏幕时,可能会发生这种情况。系统也可以onStop() 在活动完成运行时调用,并且即将终止。

特殊情况

一、当屏幕发生旋转时,当前的 Activity 会被销毁,重新创建一个新的活动
生命周期为:
onPause(): Activity 暂停。通常在这里保存一些临时数据,停止动画等。
onStop(): Activity 停止,变得不可见。在这里可以释放一些不再需要的资源。
onDestroy(): Activity 被销毁。在这里释放所有资源,取消注册监听器等。
Activity 重新创建:
onCreate(Bundle savedInstanceState): 新的 Activity 实例被创建。savedInstanceState 参数可能包含之前保存的状态信息,如果之前调用了 onSaveInstanceState() 方法。
onStart(): Activity 变得可见。
onResume(): Activity 恢复,重新获得焦点,可以与用户交互。

注意:在 activity 销毁前,会调用 onRestoreInstanceState 方法,将之前的数据(对象等等)通通保存下来,但是控件上的信息不会被保留。

二、优先级,如果内存不足,会把优先级低的活动 stop 掉
优先级–高到低

正在运行的活动,
在后台不可见的活动,
执行过stop的活动

Activity的启动模式

Activity 的启动模式 (Launch Mode) 定义了当用户启动一个新的 Activity 时,系统如何处理 Activity 的实例。 它们定义在 AndroidManifest.xml 文件中,通过 标签的 android:launchMode 属性指定。

Android 提供了四种启动模式:

standard (默认模式):

每次启动 Activity,都会创建一个新的实例,并将其压入任务栈的顶部。
多个实例可以存在于同一个任务栈中。
可以通过 new Intent(context, MyActivity.class) 启动。
应用场景: 大多数情况下都适用,适用于需要多个实例的场景,比如浏览网页、查看多个联系人等。

singleTop:

如果目标 Activity 已经位于任务栈的栈顶,则不会创建新的实例,而是会调用现有实例的 onNewIntent() 方法,并将新的 Intent 传递给它。
如果目标 Activity 不在栈顶,则会创建一个新的实例,并将其压入栈顶。
应用场景: 适用于接收推送消息的 Activity,避免重复创建实例。比如消息通知栏点击跳转的 Activity。

singleTask:

系统创建一个新的任务栈 (Task),并将 Activity 的实例放入该任务栈中。 (如果指定的 taskAffinity 已经存在,则直接使用该 taskAffinity 的栈)
如果系统中已经存在该 Activity 的实例,并且位于某个任务栈中,则系统会将该任务栈移动到前台,并调用现有实例的 onNewIntent() 方法。 不会创建新的实例。
如果启动 singleTask Activity 时,任务栈中有其他的 Activity,这些 Activity 会被销毁。 (注意,这取决于具体的实现,行为可能有些不同。)
应用场景: 适用于应用的主 Activity,确保只有一个实例存在,避免用户多次启动应用。 例如,Launcher Activity。

singleInstance:

与 singleTask 类似,系统创建一个新的任务栈,并将 Activity 的实例放入该任务栈中。
但与 singleTask 不同的是,这个任务栈中只能有这一个 Activity 实例。 任何其他的 Activity 都不会被放入这个任务栈。
当其他 Activity 从这个 Activity 启动时,它们会被放入其他的任务栈中。
应用场景: 适用于需要与其他应用共享的 Activity,例如拨打电话的 Activity。 可以确保该 Activity 独立于其他应用的任务栈。

启动模式 实例数量 位置 行为 应用场景
standard 多个 栈顶 每次启动都创建新实例。 浏览网页,查看多个联系人等。
singleTop 多个,栈顶只有一个 栈顶 如果栈顶是该 Activity,则调用 onNewIntent(),否则创建新实例。 接收推送消息的 Activity。
singleTask 一个 任务栈根 如果已存在实例,则将任务栈移动到前台,调用 onNewIntent(),否则创建新实例,并创建新的任务栈。 确保只有一个实例,如果启动时栈中有其他Activity,可能会被销毁(取决于具体实现) 应用的主 Activity (Launcher)。
singleInstance 一个 独立任务栈 创建新的任务栈,只有这一个 Activity 实例。 与其他应用共享,确保该 Activity 独立于其他应用的任务栈。 拨打电话的 Activity。

Activity 与 Fragment

Activity

定义: Activity 代表一个单独的屏幕,是用户可以交互的独立组件。 可以理解为应用的一个窗口。
生命周期: 拥有完整的生命周期,包括 onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()。
UI: 负责整个屏幕的 UI 显示和用户交互。
独立性: 可以独立运行,有自己的任务栈。
依赖性: 不依赖于其他组件,是顶层组件。
使用场景: 应用程序中的每个屏幕通常对应一个 Activity。
Fragment

定义: Fragment 是 Activity 的一部分,代表 Activity 界面中的一部分 UI。 可以理解为 Activity 的一个模块化部分。
生命周期: Fragment 的生命周期依赖于宿主 Activity,拥有自己的生命周期回调,但其状态会受到宿主 Activity 的影响。 生命周期方法包括 onAttach(), onCreate(), onCreateView(), onActivityCreated(), onStart(), onResume(), onPause(), onStop(), onDestroyView(), onDestroy(), onDetach()。
UI: 负责 Activity 界面的一部分 UI 显示和用户交互。
独立性: 不能独立运行,必须依附于 Activity。
依赖性: 依赖于 Activity,是 Activity 的子组件。
使用场景: 将一个 Activity 的 UI 分解为多个可重用的模块,可以在不同的 Activity 之间共享。 例如,在平板电脑上,可以在一个 Activity 中同时显示列表和详细信息;在手机上,可以在不同的 Activity 中显示它们。

特性 Activity Fragment
本质 独立屏幕 Activity 的一部分
生命周期 完整的生命周期 依赖于宿主 Activity 的生命周期
UI 负责整个屏幕的 UI 负责 Activity 界面的一部分 UI
独立性 可以独立运行 必须依附于 Activity
可重用性 较低 较高,可以在多个 Activity 之间重用
任务栈 有自己的任务栈 没有自己的任务栈,依附于宿主 Activity 的任务栈
内存占用 通常比 Fragment 消耗更多的资源 比 Activity 消耗更少的资源
主要用途 构建应用程序的各个屏幕 将 Activity 的 UI 分解为模块化组件,提高代码可重用性,适应不同屏幕尺寸的设备

创建:
图片

销毁:
图片

Service

Service 可以将其视为在后台执行长时间运行操作的组件,它没有用户界面。 Service 适用于执行不需要用户交互的任务,例如播放音乐、下载文件、处理网络事务或定期更新数据。

Service 的理解:

后台运行: Service 主要设计为在后台运行,即使应用程序不可见或被用户切换到其他应用。
无界面: Service 本身没有用户界面。 它默默地执行任务,不直接与用户交互。
长时间运行: Service 适用于执行需要较长时间才能完成的任务,例如下载大文件、处理复杂的网络请求或持续监听传感器数据。
独立于 Activity: Service 的生命周期与启动它的 Activity 无关。 即使启动 Service 的 Activity 被销毁,Service 仍然可以继续运行,直到它自行停止或被系统停止。
系统组件: Service 是 Android 系统的重要组件,可以被其他应用程序或系统服务调用。

Service 的两种启动方式:

Started Service (启动服务):

启动方式: 通过调用 startService() 方法启动。
生命周期:
onCreate(): Service 创建时调用,只调用一次。
onStartCommand(): 每次调用 startService() 方法时都会调用。你需要在该方法中处理具体的业务逻辑。 可以通过返回值来控制Service被kill后的行为
START_NOT_STICKY: Service 被系统杀死后,不会自动重启。
START_STICKY: Service 被系统杀死后,会尝试自动重启。 但是,Intent 将为 null。
START_REDELIVER_INTENT: Service 被系统杀死后,会尝试自动重启,并且会将最后一次的 Intent 重新发送给 Service。
onDestroy(): Service 停止时调用,在这里释放资源。
停止方式: 通过调用 stopSelf() 方法或由其他组件调用 stopService() 方法来停止。
特点:
适用于执行一次性的、不需要与启动组件进行交互的任务。
Service 启动后会一直运行,直到显式停止或被系统杀死。
启动组件(例如 Activity)与 Service 之间没有直接的绑定关系。
使用场景:
下载文件
播放音乐
执行后台数据同步
监听网络连接状态

Bound Service (绑定服务):

启动方式: 通过调用 bindService() 方法启动。
生命周期:
onCreate(): Service 创建时调用,只调用一次。
onBind(): 当其他组件(例如 Activity)通过 bindService() 绑定到 Service 时调用。 必须返回一个 IBinder 对象,用于客户端与 Service 进行交互。
onUnbind(): 当所有客户端都与 Service 解绑时调用。
onDestroy(): Service 停止时调用,在这里释放资源。
停止方式: 当所有客户端都与 Service 解绑时,Service 会自动停止。 也可以通过调用 unbindService() 方法来解绑。
特点:
允许组件(例如 Activity)与 Service 进行交互,例如调用 Service 中的方法、获取 Service 的状态等。
Service 的生命周期与绑定到它的组件密切相关。 当所有客户端都与 Service 解绑时,Service 就会自动停止。
适用于需要与启动组件进行频繁交互的任务。
使用场景:
音乐播放器(允许 Activity 控制播放、暂停、调整音量等)
数据提供器(允许 Activity 查询数据)
远程过程调用 (RPC)

两种启动方式的区别:

特性 Started Service Bound Service
启动方式 startService() bindService()
交互 不与启动组件交互 允许与启动组件交互
停止方式 stopSelf()stopService() unbindService() (所有客户端解绑后自动停止,或显式调用)
生命周期 独立于启动组件 与绑定组件密切相关
主要用途 执行一次性的后台任务,不需要与组件交互 允许组件与 Service 进行交互,例如调用方法、获取状态等

BroadcastReceiver

BroadcastReceiver 是 Android 系统中的一个组件,用于接收并响应系统或应用程序发送的广播消息 (Intent)。 它可以理解为一种“消息监听器”,监听特定类型的事件发生,并在事件发生时执行相应的操作。

核心概念:

广播 (Broadcast): 一种全局通知机制,允许应用程序向系统或其他的应用程序发送消息。
Intent: Android 中用于传递消息的对象。 广播消息也是通过 Intent 对象来传递的。
广播接收器 (BroadcastReceiver): 用于接收特定类型的广播消息,并在消息到达时执行相应的操作。
IntentFilter: 用于指定 BroadcastReceiver 想要接收的广播消息的类型。 可以通过 Action、Category、Data 等属性进行过滤。

主要作用:

监听系统事件: 例如,监听网络连接状态改变、电池电量低、屏幕关闭等系统事件。
监听应用程序事件: 例如,监听应用程序安装、卸载、更新等事件。
接收应用程序之间的消息: 应用程序可以通过发送自定义广播消息,实现应用程序之间的通信。

广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;然而有序广播是按照接收者声明的优先级别(声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C。A得到广播后,可以往广播里存入数据,当广播传给B时,B可以从广播中得到A存入的数据。

两种注册方式:

静态注册 (在 AndroidManifest.xml 中声明):

在 AndroidManifest.xml 文件中使用 标签声明 BroadcastReceiver,并使用 标签指定要接收的广播消息类型。
特点:
应用程序未运行也能接收广播消息。
常驻内存,会增加应用程序的资源消耗。
适用场景:
需要监听一些重要的系统事件,即使应用程序未运行也需要及时响应。

示例:

1
2
3
4
5
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>

动态注册 (在代码中注册):

在代码中使用 registerReceiver() 方法注册 BroadcastReceiver,并使用 IntentFilter 对象指定要接收的广播消息类型。
特点:
只有应用程序在运行状态才能接收广播消息。
不会增加应用程序的常驻内存消耗。
适用场景:
只需要在应用程序运行状态下监听的广播消息。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyActivity extends Activity {
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 处理广播消息
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter("my_action");
registerReceiver(mReceiver, filter);
}

@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}

ContentProvider

ContentProvider是android四大组件之一的内容提供器,它主要的作用就是将程序的内部的数据和外部进行共享,为数据提供外部访问接口,被访问的数据主要以数据库的形式存在,而且还可以选择共享哪一部分的数据。这样一来,对于程序当中的隐私数据可以不共享,从而更加安全。ContentProvider是android中一种跨程序共享数据的重要组件。

核心概念:
数据共享: ContentProvider 的主要目的是允许不同的应用程序安全地访问和修改彼此的数据。
结构化数据: ContentProvider 提供的数据通常是结构化的,例如数据库表、文件等。
统一接口: ContentProvider 提供了一套标准的 API (CRUD 操作),使得应用程序可以使用统一的方式访问不同来源的数据。
安全性: ContentProvider 可以通过权限控制,限制对数据的访问。
URI (Uniform Resource Identifier): 用于唯一标识 ContentProvider 提供的数据。

主要作用:
数据共享: 允许不同的应用程序访问和修改彼此的数据。
数据封装: ContentProvider 将底层的数据存储方式 (例如数据库、文件) 封装起来,应用程序无需关心数据的具体存储方式。
数据访问控制: ContentProvider 可以通过权限控制,限制对数据的访问。
数据变更通知: ContentProvider 可以在数据发生变化时,通知其他应用程序。

如何使用 ContentProvider:

创建 ContentProvider:

创建一个类,继承 ContentProvider 类。
实现 onCreate()、query()、insert()、update()、delete()、getType() 方法。
在 AndroidManifest.xml 文件中使用 标签声明 ContentProvider。

示例:

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
JAVA
public class MyContentProvider extends ContentProvider {

// Content URI
public static final String AUTHORITY = "com.example.myapp.MyProvider";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/data");

// 数据类型
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.example.myapp.data";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.example.myapp.data";

@Override
public boolean onCreate() {
// 初始化数据存储
return true;
}

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
// 查询数据
return null;
}

@Nullable
@Override
public String getType(@NonNull Uri uri) {
// 返回数据类型
return null;
}

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
// 插入数据
return null;
}

@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
// 删除数据
return 0;
}

@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
// 更新数据
return 0;
}
}

清单文件XML

1
2
3
4
5
6
<provider
android:name=".MyContentProvider"
android:authorities="com.example.myapp.MyProvider"
android:exported="true"
android:readPermission="com.example.myapp.READ_DATA"
android:writePermission="com.example.myapp.WRITE_DATA"/>

访问 ContentProvider:

使用 ContentResolver 对象访问 ContentProvider 提供的数据。
使用 query()、insert()、update()、delete() 方法执行 CRUD 操作。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
JAVA
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// 访问 ContentProvider
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(MyContentProvider.CONTENT_URI, null, null, null, null);

// ... 处理查询结果 ...
}
}

权限控制:

ContentProvider 可以通过权限控制,限制对数据的访问。

android:readPermission: 指定读取数据的权限。
android:writePermission: 指定写入数据的权限。
其他应用程序如果需要访问 ContentProvider 提供的数据,需要在 AndroidManifest.xml 文件中声明相应的权限。