Android客户端青训营课程(第二课)笔记|青训营笔记

104 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的第3天
该笔记主要是对青训营第二课知识点的简单总结和自己的小思考。

程序

开发者视角

what:代码+资源
why:改变世界
how:知识+经验

用户视角

what:界面、互动、记忆
why:工具、视频、游戏
how:应用商店、搜索引擎、官网下载、三方引流

【视角不同,对同一事物抽象出的模型也会不相同】

Android基础组件

四大组件的小扩展

界面组件(Activity & Fragment)

Activity(界面容器)

what:界面容器
why:前台交互、程序入口、布局容器
how:
三部曲:注册、布局、绑定 image.png 各种方法名称及作用:
onCreate():创建时回调,一般在此处创建视图和绑定数据
onStart():已启动,即将进入前台
onResume():与用户开始交互,位于Activity栈顶
onPause():Activity失去焦点或已暂停,Activity界面部分可见,
下一个生命周期是onResume()或onStop()
onStop():Activity不再可见,下一个回调是onRestart()或onDestory()
onRestart():重启已停止的Activity,下一个回调是onStart()
onDestory():销毁Actvity,释放该Activity的所有资源
onSaveInstanceState():在非正常关闭时回调,用于保存数据,不支持持久化数据
onRestoreInstanceState() /onCreate():用于恢复数据
【记好常用场景下方法的使用,能够适用大多数情况】
打开/启动界面 onCreate()-onStart()-onResume()
关闭/退出界面 onPause()-onStop()-onDestroy()
部分遮挡 onPause()
部分遮挡恢复 onResume()
完全遮挡 onPause()-onSaveInstanceState()-onStop()
完全遮挡恢复 onStart()-onResume()
配置改变场景销毁 onSaveInstanceState()-onPause()-onStop()-onDestory()
配置改变场景重建 onCreate()-onStart()-onRestoreInstanceState()-onResume()
配置改变不重建Activity:AndroidManifest中配置Activity节点的configChange属性
(local:语言改变、fontScale:字体大小改变、orientation:旋转屏幕、keybordHidden:键盘显示隐藏 等)onConfigurationChanged()
后台回收销毁:不会有实际处理
后台回收重建:onCreate()-onState()-onRestoreInstanceState()-onResume()
【记录使用界面时长,计时打点onResume()开始,兼容安卓4.X应在onPause()结束,若不兼容(即安卓5.0以后)在onStop()】
Activity启动模式:
standard:默认模式,允许Activity重复
singleTop:栈顶复用,不允许Activity连续重复
singleTask:栈内复用,不允许同个栈内Activity重复
SingleInstance:全局复用,整个系统不允许Activity重复

方案:解决接电话Crash问题
原因:页面被回收导致本地变量被置空
问题解决: 1添加判空逻辑比避免空指针问题
2在页面回收生命周期中储存数据,页面重建时进行恢复onSaveInstanceState()中写入需要保存的数据onRestoreInstanceState()进行数据恢复

Fragment(轻量级界面容器)

what:页面容器
why:意图是碎片化,实际上提供了更快的速度和进行组件分离
how:
【Fragment解决Activity间的切换不流畅,轻量切换】
1创建Fragment布局文件
2创建Fragment子类,加载布局文件
3Activity加载Fragment
3.1静态加载:布局中绑定
3.2动态加载:FragmentManager加载
image.png
各种方法名称及作用
onAttach():Fragment和Activity建立关联时调用
onCreateView(): 当Fragment创建视图时调用
onActivityCreated():Activity的onCreate()方法已返回时调用
onDestoryView():当Fragment中的视图被移除时调用
onDetach():Fragment和Activity取消关联时调用
【若在onAttach()之前,访问Activity,容易取到空,造成空指针的问题】
【同样地,常用场景下的方法使用能够搞定大多数情况】
启动 onAttach()-onCreate()-onCreateView()-onActivityCreated()-onStart()-onResume()-Resumed
退出 Resumed-onPause()-onStop()-onDestoryView()-onDestory()-onDetach()
部分覆盖 Resumed-onPause()-Paused
部分遮挡恢复 Paused-onResume()-Resumed
完全覆盖 Resumde-onPause()-onStop()-onDestoryView()
完全遮挡恢复 onCreateView()-onActivityCreated()-onStart()-onResume()-Resumed
【注:Fragment生命周期可通过FragmentTransaction.setMaxLifecycle()手动干预】

与Activity交互
组件获取
1Fragment获取Activity中的组件:getActivity().findViewByld(R.id.xxx)
2Activity获取Fragment中的组件:getFragmentManager.findFragmentByld(R.id.Feagment_xxx)
数据传递
1Activity传数据给Fragment:setArguments(Bundle bundle)
2Fragment传数据给Activity:

  1. 通过对象直接传递(方法调用/接口调用)
  2. 通过viewmodel/handler/broadcast/eventbus等通信(异步方式)

服务组件(Service)(后台服务)

【Service 分为两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于其他组件和 Service 的交互。】
1注册:AndroidManifest中使用<service.../>标签
2创建:建立相应的Service实现类
3加载:startService()/bindService()

Service(与Activity通信)
1定义Binder子类,并实现getService()方法,返回Service对象
2实现Service类onBind()方法,返回上述Binder对象
3实例化ServiceConnection对象,实现onServiceConnected()方法,从中获取到Service实例
4Activity中调用bindService()方法,并传递步骤3的ServiceConnection对象,将流程跑起来
5Activity既可以通过调用Service实例中的方法进行直接通信

广播组件(Broadcast)

静态广播
1注册:AndroidManifest中使用<receiver.../><intent-filter.../>
2创建:建立相应的BroadcastReceiver实现类
3接收:在步骤2类onReceive()中接收广播
4发送:Context.sendBroadcast()

动态广播
注册:Context.registerReceiver()
常用系统广播(需要系统权限) Intent.ACTION_XXXXX_XXXXX(具体操作)
【target 26 之后,无法在 AndroidManifest 显示声明大部分广播(静态广播),除了一部分必要的广播】

数据组件(ContentProvider & contentResolver)

ContentProvider

【ContentProvider管理对结构化数据集的访问。它封装数据并且提供用于定义数据安全性的机制。内容提供程序是连接一个进程中的数据与另一个进程中运行的代码的标准界面。】
生产者
注册:AndroidManifest中使用<provider.../>
属性:authorities/exported/readPermission/writePermission
创建:建立相应的ContentProvider实现类
方法:onCreate/getType/insert/delete/update/query

消费者
声明:AndroidManifest中声明权限 使用:context.getContentResolver() 方法:insert/delete/update/query 【对于一个 ContentProvider 组件来说,它的内部需要实现增删该查这四种操作】

Intent(意图组件)

1 Context.startActivity(Intent)
2 Context.startService(Intent)
3 Context.sendBroadcast(Intent)
基本用法
1显式Intent:setComponent/setClass指定具体类
2隐式Intent: Action(动作)、 Date(数据)、 Category(类别)、 Type(数据类型)、 Component(组件)、 Extra(扩展信息)、 Flag(标志位)
系统能力:电话、短信、网页、邮件、地图、拍照、设置、市场
使用:startActivity(intent)

例:需求-图片浏览器
1实现一个图片浏览APP(Activity+Fragment)
相册页面->(GridView+Adaptor)+->大图页面(GridView+Adaptor)+调用相机->(Viewpaper+Adaptor)(Intent)
2旋转屏幕场景(Activity生命轴器)
3内置升级能力(Service使用)
4单一首页(SingleTask)
5相关图片(SingleTop)
6扫描所有图片(ContentProvider)
7提供图片选择能力给系统(Intent)

Android通信组件

Handler(线程通信)

1创建:新建Handler,实现handleMessage(Message)
2构建Message:what/setData()
3发送:子线程调用的Handler.sendMessage(Message)发送Message(发送)
4处理:在Handler的handlerMessage(Message msg)主线程更新UI(接收)

image.png
核心原理:消息队列
【Looper:消息泵,是 MessageQueue 的管理者,会不断从 MessageQueue 中取出消息,并将消息分给对应的 Handler 处理,每个线程只有一个 Looper。looper唤醒机制,不会卡死】

Binder(进程通信)

【Binder 本身是 C/S 架构,更符合Android系统的架构】
常用IPC方案对比
IPC方式和对应数据拷贝次数
共享内存(0)、Binder(1)、Socket/管道/消息队列(2)
【Binder少一次数据拷贝,提高了整体性能】
【为什么不用共享内存,进程的用户空间隔离,数据不可共享】   基本用法
服务端
1定义一个AIDL文件(定义AIDL协议文件) 2实现描述的接口,编写service (实现Service) 3如果有实体类,需要提供实体类(jar包形式)

客户端
1拿到AIDL文件 (拿到AIDL协议文件)
2绑定服务,获得接口持有对象 (绑定Service)
【线程和协程,kotlin的语法糖】
原理:匿名共享内存、Binder驱动、ServiceManager