这是我参与「第四届青训营 」笔记创作活动的第2天。
读前须知:我是安卓方向零基础的新手,这个系列的笔记将主要用于记载我认为重要的知识点,不一定适用于所有人的学习情况。虽是新手但我依旧会尽力避免出现错误,不过如果没能完全避免,还希望读者能不惜笔墨地指出。
一、本堂课重点内容:
- 安卓系统基础组件介绍
二、详细知识点介绍:
-
安卓系统基础组件介绍
-
界面组件Activity和Fragment
-
Activity的作用
Activity的是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务。Activity中所有操作都与用户密切相关,是一个负责与用户交互的组件,可以通过
setContentView(View)来显示指定控件。在一个android应用中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。 -
Activity的基本用法
Activity都必须要在AndroidManifest.xml配置文件里注册,并且必须适当地管理 Activity 的生命周期。
-
Activity的生命周期
Activity的回调九个回调函数。在使用Activity的过程中可以不用实现所有的回调方法。
onCreate(): 创建时回调,一般在此处创建视图和绑定数据onStart(): 已启动,即将进入前台onResume(): 与用户开始交互,位于Activity栈顶onPause(): Actvity失去焦点或已暂停,Activity界面部分可见,下一个生命周期是onResume()或onStop()onStop(): Activity不再可见,下一个回调是onRestart()或onDestory()onRestart():重启已停止的Activity,下一个回调是onStart()onDestory(): 销毁Actvity,释放该Activity的所有资源onSaveInstanceState(): 在非正常关闭时回调,用于保存数据,不支持持久化数据onRestoreInstanceState()/onCreate(): 用于恢复数据
Activity在生命周期里拥有四种基本状态:
-
Active/Running 一个新 Activity 启动入栈后,它显示在屏幕最前端,处理是处于栈的最顶端(Activity栈顶),此时它处于可见并可和用户交互的激活状态
-
Paused Activity失去焦点,或者说一个新的Activity没有完全覆盖掉旧的Activity,此时它仍然可见,但已经失去了焦点故不可与用户进行交互。
-
Stopped 如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被强行终止掉。
-
Killed 如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。
回调函数在状态转移中所处的位置如图所示:
-
Activity的四种启动模式
-
standard:默认的启动方式。在该模式中,每启动一个新活动,都会创建一个新的实例,并在任务栈中入栈,处于栈顶的位置。假设你不停地进入同一个活动,你点击了十次,就要返回十次才能退出程序,因为你在返回栈中创造了十个相同的实例,尽管活动是一样的。
-
singleTop:启动一个新活动时,系统会检查该活动是否已经位于任务栈栈顶,如果是的话直接使用已存在的栈顶活动,否则就创建新活动并压入栈顶。
-
singleTask:和 singleTop 类似,不过这里是检查整个任务栈的活动,如果发现已经存在该活动就将位于该活动上方的活动全部出栈,该活动成为新的栈顶。
-
singleInstance:最特殊的模式,系统为该模式的活动分配一个独立的任务栈,该任务栈有且只有一个该活动实例。也就是说,如果已经创建过目标活动实例,那么将不会创建新的任务栈,而是唤醒之前创建过的活动实例。
-
-
Fragment与Activity的关系
Fragment能将界面划分为离散的区块,从而将模块化和可重用性引入 Activity 的界面。Activity 是围绕应用的界面放置全局元素(如抽屉式导航栏)的理想位置。相反,Fragment 更适合定义和管理单个屏幕或部分屏幕的界面。
假设有一个响应各种屏幕尺寸的应用。在较大的屏幕上,该应用应显示一个静态抽屉式导航栏和一个采用网格布局的列表。在较小的屏幕上,该应用应显示一个底部导航栏和一个采用线性布局的列表。在 Activity 中管理所有这些变化因素可能会很麻烦。将导航元素与内容分离可使此过程更易于管理。然后,Activity 负责显示正确的导航界面,而 Fragment 采用适当的布局显示列表。
-
Fragment的基本用法
- 创建Fragment布局文件
- 创建Fragment子类,加载布局文件
- Activity加载Fragment
3.1 静态加载:布局中绑定
3.2 动态加载:FragmentManager加载
-
Fragment的生命周期
五个回调函数:
onAttach()Fragment和Activity建立关联时调用onCreateView()当Fragment创建视图时调用onActivityCreated()Activity的onCreate()方法已返回时调用onDestroyView()当Fragment中的视图被移除时调用onDetach()Fragment和Activity取消关联时调用
Fragment与Activity生命周期的关系:
-
Fragment与Activity的交互
组件获取:
- Fragment获取Activity中的组件:
getActivity().findViewByld(R.id.xxx) - Activity获取Fragment中的组件:
getFragmentManager.findFragmentByld(R.id.fragment_xox)
数据传递:
- Activity传数据给
Fragment: setArguments(Bundle bundle) - Fragment传数据给Activity:
- 通过对象直接传递(方法调用/接口调用)
- 通过
viewmodel / handler / broadcast / eventbus等通信
- Fragment获取Activity中的组件:
-
-
服务组件Service
-
基本用法
- 注册: AndroidManifest.xml中使用<service.../>标签
- 创建: 建立相应的Service实现类
- 加载:
startService() / bindService()
-
生命周期
回调函数:
onCreate(): 创建onStartCommand(): 开始onDestroy(): 销毁onBind(): 绑定onUnbind(): 解绑
和生命周期的关系如图:
-
Service和Activity的交互
- 定义Binder子类,并实现
getService()方法,返回Service对象 - 实现Service类
onBind()方法,返回上述Binder对象 - 实例化ServiceConnection对象,实现
onServiceConnected()方法,从中获取到Service实例 - Activity中调用
bindService()方法,并传递步骤3的ServiceConnection对象,将流程跑起来 - Activity既可以通过调用Service实例中的方法进行直接通信,也可以通过broadcast(广播)的形式通信
- 定义Binder子类,并实现
-
-
广播组件Broadcast
-
基本用法
静态广播
- 注册: AndroidManifest中使用
<receiver../><intent-filter.../> - 创建: 建立相应的BroadcastReceiver实现类
- 接收: 在步骤2类
onReceive()中接收广播 - 发送:
Context.sendBroadcast()
动态广播
- 注册: 在需要的地方使用
registerReceiver()和unregisterReceiver() - 创建: 声明一个ACTION
- 接收与发送都和静态广播一致
- 注册: AndroidManifest中使用
-
作用范围
静态广播:整个App的生命周期 动态广播:注册和注销期间
-
-
数据组件ContentProvider和ContentResolver
-
基本用法
生产者
- 注册: AndroidManifest中使用<provider.../>
属性:
authorities / exported / readPermission / writePermission - 创建: 建立相应的ContentProvider实现类
方法:
onCreate / getType / insert / delete / update / query
消费者
- 声明: AndroidManifest中声明权限
- 使用:
context.getContentResolver()方法:insert / delete / update / query
- 注册: AndroidManifest中使用<provider.../>
属性:
-
-
意图组件Intent
-
Intent的作用
Android意图是一个要执行的操作的抽象描述。它可以通过 startActivity 来启动一个活动,broadcastIntent 来发送广播到任何对它感兴趣的广播接受器组件,startService(Intent) 或者bindService(Intent, ServiceConnection, int) 来与后台服务通讯。意图本身(一个 Intent 对象)是一个被动的数据结构,保存着要执行操作的抽象描述。
-
显式Intent
显式意图用于连接应用程序的内部世界,假设你需要连接一个活动到另外一个活动,我们可以通过显示意图。这些意图通过名称指定目标组件,一般用于应用程序内部信息 - 比如一个活动启动一个下属活动或者启动一个兄弟活动。
// 通过指定类名的显式意图 Intent i = new Intent(FirstActivity.this, SecondAcitivity.class); // 启动目标活动 startActivity(i); -
隐式Intent
相比于显式Intent,隐式Intent则含蓄了许多,它并不明确指出我们想要启动哪一个活动,而是指定了一系列更为抽象的 action和 category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。 通过在AndroidManifest.xml中
<activity>标签下配置<intent-filter>的内容,可以指定当前活动能够响应的Action(动作)、Data(数据)、Category(类别)、Type(数据类型)、Component(组件)、Extra(扩展信息)、Flag(标志位)。
-
-
三、实践练习例子:
- 建议复现一下《第一行代码》中关于生命周期的例子、或网络上讲述生命周期的代码样例,之后对各个组件生命周期的理解会更加清晰。
四、课后个人总结:
-
本章介绍的各个基础组件的内容比较多,需要细心掌握。
-
各个组件的生命周期和回调函数容易弄混,需要仔细辨别。
五、引用参考: