1.在 manifest 配置文件中申明 activity
manifest配置文件是一个包含元数据的XML文件,用来向Android操作系统描述应用。该文件总是以AndroidManifest.xml命名,可在项目的app/manifests目录中找到它。
2. 启动 activity
一个 activity 启动另一个 activity 最简单的方式就是使用 startActivity(Intent) 函数
ActivityManager 该启动哪个 activity 呢? 得看 Intent 参数里的信息。
ActivityManager并不直接启动Activity,它是一个系统服务,用于管理应用程序的生命周期和任务栈。它可以启动Activity,但是需要通过Intent来指定要启动的Activity。
如果你想通过ActivityManager启动一个Activity,可以使用以下代码:
java
Intent intent = new Intent(context, YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
其中,YourActivity是你要启动的Activity的类名,context是一个Context对象,可以是Activity或者Application的实例。通过设置Intent的标志位 FLAG_ACTIVITY_NEW_TASK,可以确保Activity在一个新的任务栈中启动。
请注意,使用ActivityManager启动Activity需要声明启动权限,否则会抛出SecurityException异常。你可以在AndroidManifest.xml文件中添加以下声明:
java
<uses-permission android:name="android.permission.REAL_GET_TASKS"/>
同时,由于Android系统的安全机制,只有系统应用程序才能使用ActivityManager启动Activity。
使用ActivityManager启动其他应用程序的Activity,因为这会涉及到跨应用程序的安全问题。如果你想启动其他应用程序的Activity,可以使用以下代码:
java
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.package", "com.example.package.YourActivity"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
其中,"com.example.package"是目标应用程序的包名,"com.example.package.YourActivity"是要启动的Activity的完整类名。同样需要声明启动权限,并且需要目标应用程序的签名与你的应用程序相同,否则会抛出SecurityException异常。
需要注意的是,使用ActivityManager启动Activity并不是最常用的启动Activity的方式,通常我们会使用Context.startActivity()方法来启动Activity。
3. 基于 Intent 的通信
intent对象是component用来与操作系统通信的一种媒介工具。目前为止,我们唯一见过的component就是activity。实际上还有其他一些component:service、broadcast receiver以及content provider。
在启动 activity 前,ActivityManager 会确认指定的 Class 是否已在 manifest 配置文件中声明。如果已经完成声明,则启动 activity , 应用正常运行。 反之,则抛出 ActivityNotFoundException 异常,应用崩溃。
这就是必须在 manifest 配置文件中声明应用的全部 activity 的原因。
在Android应用程序中,Manifest配置文件中声明应用的全部Activity是必须的。这是因为Android系统需要知道应用程序中所有的Activity,以便在运行时正确地管理Activity的生命周期和任务栈。
具体来说,Manifest配置文件中声明应用的全部Activity可以实现以下几个方面的功能:
-
声明Activity的入口点:在Manifest文件中声明的Activity可以作为应用程序的入口点,即启动应用程序时默认启动的Activity。
-
定义Activity的属性:在Manifest文件中声明的Activity可以定义Activity的属性,如主题、启动模式、配置变化等。
-
管理Activity的生命周期:在Manifest文件中声明的Activity可以帮助Android系统正确地管理Activity的生命周期,确保Activity在需要时正确地创建、启动、暂停、恢复和销毁。
-
管理任务栈:在Manifest文件中声明的Activity可以帮助Android系统正确地管理
1. 显示 intent 与 隐式 intent
通过指定Context与Class对象,然后调用intent的构造函数来创建Intent,这样创建的是显式intent。在同一应用中,我们使用显式intent来启动activity。
一个应用的activity如需启动另一个应用的activity,可通过创建隐式intent来处理。
4. activity 间的数据传递
1. 使用intent extra
作为extra信息,附加在传入startActivity(Intent)函数的Intent上发送出去。 extra信息可以是任意数据,它包含在Intent中,由启动方activity发送出去。
接受方 activity 接收到操作系统转发的 intent 后,访问并获取其中的 extra 数据信息。 extra 也是一种键值结构。
ActivityManager 维护一个非特定应用独享的 后退栈,所有应用的 activity 都共享该后退栈。
5. Android SDK 版本与兼容
- complieSdkVersion: SDK最低版本和目标版本会通知给操作系统,而SDK编译版本只是你和编译器之间的私有信息。
- minSdkVersion : 操作系统将拒绝将应用安装在低于此标准的设备上。
- targetSdkVersiion :目标版本的设定值会告诉Android应用是为哪个API级别设计的。大多数情况下,目标版本即最新发布的Android版本。
这些都可以修改,但是在修改之后,需要项目和 gradle 更改重新同步后才能生效。
文档来源: 平台、Android Studio、Google Play、Android Jetpack、参考文档和新闻
6. UI fragment 与 fragment 管理器
6.2 引入 fragment
采用 fragment 而不是 activity 来管理应用 UI 可让应用具有灵活性。
fragment 是一种控制器对象, activity 可委派它执行任务。这些任务通常就是管理用户界面。
管理用户界面的fragment又称为UI fragment。它也有自己的视图(由布局文件实例化而来)。fragment视图包含了用户可以交互的可视化UI元素。
activity 试图能预留位置供 fragment 视图插入。
可以联合使用fragment及activity来组装或重组用户界面。
activity 负责以一个明细 fragment 替换另一个明细 fragment 视图切换的过程中,也不用销毁 activity 了。
除列表明细类应用外,使用UI fragment将应用的UI分解成构建块,同样适用于其他类型的应用。例如,利用单个构建块,可以方便地构建分页界面、动画侧边栏界面等更多定制界面。
- activity 在其视图层级中提供一个位置,用来放置 fragment 视图。
- fragment 本身没有在屏幕上显示视图的能力。
- 只有将其视图放置在 activity 的视图层级结构中,fragment 视图才能显示在屏幕上。
MainActivity 托管 CrimeFragment
这里 CrimeFragment 负责创建并管理用户界面,以及与模型对象进行交互。
获取FragmentManager之后,再获取一个fragment交给它管理。
fragment 事务被用来添加、移除、附加、分离或替换替换fragment队列中的fragment。它们允许你按组执行多个操作,例如,同时添加多个fragment到不同的视图容器里。这是使用fragment动态组装和重新组装用户界面的关键。
FragmentManager维护着一个fragment事务回退栈,你可以查看、历数它们。如果fragment事务包含多个操作,那么在事务从回退栈里移除时,其批量操作也会回退。基于这个原因,UI状态更好控制了。
kotlin
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (currentFragment == null) {
val fragment = CrimeFragment() supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit() }
FragmentManager 使用 FrameLayout 的资源ID来识别 CrimeFragment。 使用容器视图资源 ID 识别 UI fragment 就是 FragmentManager 的一种内部实现机制。
如果要向activity中添加多个fragment,通常需要分别为每个fragment创建具有不同ID的各种容器。
这里代码步骤:
- 如果要向activity中添加多个fragment,通常需要分别为每个fragment创建具有不同ID的各种容器。
- 设备旋转或回收内存时,Android系统会销毁MainActivity,而后重建时,会调用MainActivity.onCreate(Bundle?)函数。activity被销毁时,它的FragmentManager会将fragment队列保存下来。这样,activity重建时,新的FragmentManager会首先获取保存的队列,然后重建fragment队列,从而恢复到原来的状态。
- 如果指定容器视图资源ID的fragment不存在,则fragment变量为空值。这时应该新建CrimeFragment,并启动一个新的fragment事务,将新建fragment添加到队列中。
FragmentManager与fragment生命周期
fragment有类似于activity的生命周期:有同样的停止、暂停和运行状态;有可以覆盖的函数,让你能在某些关键时点执行特定任务,而且,这些函数大多和activity生命周期相对应。
activity的生命周期函数由操作系统负责调用,而fragment的生命周期函数由托管activity的FragmentManager负责调用。对于activity用来管理事务的fragment,操作系统概不知情。添加fragment供FragmentManager管理时,onAttach(Context?)、onCreate(Bundle?)和onCreateView(...)函数会被调用。
托管activity的onCreate(Bundle?)函数执行后,onActivityCreated(Bundle?)函数也会被调用。因为是在MainActivity.onCreate(Bundle?)函数中添加CrimeFragment,所以fragment被添加后,该函数会被调用。
在activity处于运行状态时,添加fragment会发生什么呢?这种情况下,FragmentManager会立即驱赶fragment,调用一系列必要的生命周期函数,快速跟上activity的步伐(与activity的最新状态保持同步)。例如,向处于运行状态的activity中添加fragment时,以下fragment生命周期函数会被依次调用:onAttach(Context?)、onCreate(Bundle?)、onCreateView(...)、onViewCreated(...)、onActivityCreated(Bundle?)、onStart()以及onResume()。
一旦追上,托管activity的FragmentManager就会边接收操作系统的调用指令,边调用其他生命周期函数,让 fragment与activity保持步调一致。