Android学习笔记之四大组件
开始写这篇文章时,我也是啥也不懂,啥也不会,因此文章中一定会有许多不足甚至错误!欢迎大家批评指正!
另外,此文章参考了许多文档、教程等,都在引用出贴出了链接,但如果侵犯了作者著作权,请联系我,我会在第一时间删除。
四大组件
- 活动
Activity
- 服务
Service
- 广播接收器
BroadcastReceiver
- 内容提供程序
ContentProvider
Activity
Activity 是与用户交互的入口点。它表示拥有界面的单个屏幕。例如,电子邮件应用可能有一个显示新电子邮件列表的 Activity、一个用于撰写电子邮件的 Activity 以及一个用于阅读 电子邮件的 Activity。尽管这些 Activity 通过协作在电子邮件应用中形成一种紧密结合的用户体验,但每个 Activity 都独立于其他 Activity 而存在。因此,其他应用可以启动其中任何一个 Activity(如果电子邮件应用允许)。例如,相机应用可以启动电子邮件应用内用于撰写新电子邮件的 Activity,以便用户共享图片。Activity 有助于完成系统和应用程序之间的以下重要交互:
- 追踪用户当前关心的内容(屏幕上显示的内容),以确保系统继续运行托管 Activity 的进程。
- 了解先前使用的进程包含用户可能返回的内容(已停止的 Activity),从而更优先保留这些进程。
- 帮助应用处理终止其进程的情况,以便用户可以返回已恢复其先前状态的 Activity。
- 提供一种途径,让应用实现彼此之间的用户流,并让系统协调这些用户流。(此处最经典的示例是共享。)
简介
也就是说,Activity
是一个单独显示出来的、在前台运行的页面。一个应用程序可以有1个或多个活动,而没有任何限制。每个为应用程序所定义的活动都需要在AndroidManifest.xml
中声明。例如:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="host.skyone.helloworld">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HelloWorld">
<activity
android:name=".DisplayMessageActivity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
<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>
应用的主要活动需要在清单中声明,且意图过滤器标签中需要包含 MAIN 动作和 LAUNCHER 类别。
为了更好的展现Activity
的生命周期,引用一张来自菜鸟教程的图片:
如图所示,在Activity
的生命周期中,有几个重要的回调函数:
回调 | 描述 |
---|---|
onCreate() | 在Activity 第一次创建时调用 |
onStart() | 在Activity 为用户可见时被调用 |
onResume() | 在应用程序与用户开始可交互的时候调用 |
onPause() | 在当前Activity 将要被暂停,其他Activity 将要被恢复时调用 |
onStop() | 当活动不在可见时调用 |
onDestroy() | 当活动被系统销毁之前调用 |
onRestart() | 当活动被停止以后重新打开时调用 |
例如,
用户打开你的应用程序,onCreate()
被调用,代表Activity
正式启动
然后界面渲染完成,并调用onStart()
函数
你的程序可以开始和用户交互之前,调用onResume()
函数
这时,用户进入了QQ查看消息,你的程序变被暂停,调用onPause()
函数,注意被暂停的活动无法接受用户输入,不能执行任何代码。
好,用户回复了几条信息,并返回你的程序,你的程序又即将可以和用户交互,在这之前,调用onResume()
函数
但是如果用户返回QQ并不是回复消息,而是看了个超高清视频呢?由于用户手机内存不足,而用户要求执行的程序优先级比较高,于是很抱歉,你的程序的被kill
当用户看完视频,返回你的程序,发现OH~NO,你的程序被kill了,只能从onCreate()
开始重新创建程序
当然,如果你的程序被挂起太长时间,比如用户打开哔哩哔哩刷了一个小时的视频,那么同样的,你的程序由于挂起时间过长,也被系统停止了,但和进程被kill不同,如果用户依然需要使用你的程序,那么只需要回到你的程序,而你的程序也只需要调用onRestart()
如果程序执行完了用户的任务,即将正常退出,则在退出之前,调用onDestroy()
来进行收尾工作
示例
下面用一个例子来展示Activity
的生命周期:
package host.skyone.lifecycle;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
String msg = "Android: ";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(msg, "The onCreate() event");
}
/** 当活动即将可见时调用 */
@Override
protected void onStart() {
super.onStart();
Log.d(msg, "The onStart() event");
}
/** 当活动可见时调用 */
@Override
protected void onResume() {
super.onResume();
Log.d(msg, "The onResume() event");
}
/** 当其他活动获得焦点时调用 */
@Override
protected void onPause() {
super.onPause();
Log.d(msg, "The onPause() event");
}
/** 当活动不再可见时调用 */
@Override
protected void onStop() {
super.onStop();
Log.d(msg, "The onStop() event");
}
/** 当活动将被销毁时调用 */
@Override
public void onDestroy() {
super.onDestroy();
Log.d(msg, "The onDestroy() event");
}
}
连接手机,启动!
在Android Studio左下角的LogCat
中出现:
2021-01-07 11:57:44.614 23856-23856/host.skyone.lifecycle D/Android:: The onCreate() event
2021-01-07 11:57:44.617 23856-23856/host.skyone.lifecycle D/Android:: The onStart() event
2021-01-07 11:57:44.618 23856-23856/host.skyone.lifecycle D/Android:: The onResume() event
在手机上按返回键,出现:
2021-01-07 12:00:14.416 24658-24658/host.skyone.lifecycle D/Android:: The onPause() event
2021-01-07 12:00:14.762 24658-24658/host.skyone.lifecycle D/Android:: The onStop() event
2021-01-07 12:00:14.766 24658-24658/host.skyone.lifecycle D/Android:: The onDestroy() event
Service
服务是一个通用入口点,用于因各种原因使应用在后台保持运行状态。它是一种在后台运行的组件,用于执行长时间运行的操作或为远程进程执行作业。服务不提供界面。例如,当用户使用其他应用时,服务可能会在后台播放音乐或通过网络获取数据,但这不会阻断用户与 Activity 的交互。诸如 Activity 等其他组件可以启动服务,使该服务运行或绑定到该服务,以便与其进行交互。事实上,有两种截然不同的语义服务可以告知系统如何管理应用:已启动服务会告知系统使其运行至工作完毕。此类工作可以是在后台同步一些数据,或者在用户离开应用后继续播放音乐。在后台同步数据或播放音乐也代表了两种不同类型的已启动服务,而这些服务可以修改系统处理它们的方式:
- 音乐播放是用户可直接感知的服务,因此,应用会向用户发送通知,表明其希望成为前台,从而告诉系统此消息;在此情况下,系统明白它应尽全力维持该服务进程运行,因为进程消失会令用户感到不快。
- 通常,用户不会意识到常规后台服务正处于运行状态,因此系统可以更自由地管理其进程。如果系统需要使用 RAM 来处理用户更迫切关注的内容,则其可能允许终止服务(然后在稍后的某个时刻重启服务)。
绑定服务之所以能运行,原因是某些其他应用(或系统)已表示希望使用该服务。从 根本上讲,这是为另一个进程提供 API 的服务。因此,系统会知晓这些进程之间存在依赖关系,所以如果进程 A 绑定到进程 B 中的服务,系统便知道自己需使进程 B(及其服务)为进程 A 保持运行状态。此外,如果进程 A 是用户关心的内容,系统随即也知道将进程 B 视为用户关心的内容。由于存在灵活性(无论好坏),服务已成为非常有用的构建块,并且可实现各种高级系统概念。动态壁纸、通知侦听器、屏幕保护程序、输入方法、无障碍功能服务以及众多其他核心系统功能均可构建为在其运行时由应用实现、系统绑定的服务。
**注意:**如果您的应用面向 Android 5.0(API 级别 21)或更高版本,请使用
JobScheduler
类来调度操作。JobScheduler
的优势在于,它能通过优化作业调度来降低功耗,以及使用Doze API
,从而达到省电目的。如需了解有关使用此类的更多信息,请参阅JobScheduler
参考文档。
简介
通俗点来说:服务是一个后台运行的组件,执行长时间运行且不需要用户交互的任务。应用即使被销毁也依然可以工作。
这部分能力有限,实在无法举例,只能再次引用菜鸟教程文章的部分内容。
服务基本上包含两种状态:
状态 | 描述 |
---|---|
Started | Android的应用程序组件,如活动,通过startService() 启动了服务,则服务是Started状态。一旦启动,服务可以在后台无限期运行,即使启动它的组件已经被销毁。 |
Bound | 当Android的应用程序组件通过bindService() 绑定了服务,则服务是Bound状态。Bound状态的服务提供了一个客户服务器接口来允许组件与服务进行交互,如发送请求,获取结果,甚至通过IPC 来进行跨进程通信。 |
Service
同样拥有生命周期,可以实现监控服务状态的变化,可以在合适的阶段执行工作。
Service
包含以下回调:
回调 | 描述 |
---|---|
onStartCommand() | 其他组件(如活动)通过调用startService() 来请求启动服务时,系统调用该方法。如果你实现该方法,你有责任在工作完成时通过stopSelf() 或者stopService() 方法来停止服务。 |
onBind | 当其他组件想要通过bindService() 来绑定服务时,系统调用该方法。如果你实现该方法,你需要返回IBinder 对象来提供一个接口,以便客户来与服务通信。你必须实现该方法,如果你不允许绑定,则直接返回null。 |
onUnbind() |