这是我参与「第四届青训营 」笔记创作活动的第1天
一、什么是程序
1、开发者的渠道
2、用户的角度
二、android的基础组件
1、界面组件(Activity)
1.1 、WHAT:界面容器
1.2 、WHY:
- 前台交互
- 程序入口:就是响应用户的点击事件
- 布局容器
1.3、生命周期:
- onCreate():创建时回调,一般在此处创建视图和绑定数据
- onStart():已启动,即将进入前台,但是此时还不可见,不可交互,可以在这里打点
- onResume():与用户开始交互,位于Activity栈顶
- onPause():Activity失去焦点或已暂停,Activity界面部分可见,下一个生命周期是onResume()或onStop(),比如上面是一个弹窗,下面的Activity就会处于onPause()
- onStop():Activity不再可见,下一个回调是onRestart()或onDestory()
- onRestart():重启已停止的Activity,下一个回调是onStart()
- onDestory():销毁Activity,释放该Activity的所有资源
- onSaveInstanceState():在非正常关闭时回调(系统回收界面),用于保存数据,不支持持久化数据
- onRestoreInstanceState()/onCreate():用于恢复数据
配置改变场景:
- 销毁:Resumed-onSaveInstanceState()-onPause()-onStop()-onDestroy()
- 重建:onCreate()-onStart()-onRestoreInstanceState()-onResume()
配置改变不重建Activity:Android Manifest中配置Activity节点的configChange属性
- local:语言改变
- fontScale:字体大小改变
- orientation:旋转屏幕
- keybordHidden:键盘显示隐藏
配置改变:onConfigurationChanged():通过设置configChange()属性就不会走onSaveInstanceState()和onRestoreInstanceState()方法,而是走这个回调方法
- 问题:在程序使用的时候,有电话打进来,这时程序会Crash(崩溃)
问题原因:页面被回收导致本地变量被置空
问题解决:
-
添加判空逻辑避免空指针的产生
-
在页面回收生命周期中存储数据,页面重建时进行恢复
就是在onSaveInstanceState()写入需要保存的数据,在onRestoreInstanceState()进行数据恢复
1.4、启动模式(LauchMode)
问题引入:加入首页按钮后,点击会在当前页面栈加入新首页(这时就出现了两个首页,不应该出现两个首页),返回后首页会消失
预期:点击首页按钮回到首页,上面的页面全部退出
- standard:默认模式,允许重复
- singleTop:不允许连续重复,就是说位于栈的最顶的两个Activity不能是相同的,就是栈顶复用,当想要在栈顶重开一个和原本的栈顶Activity相同的Activity,如果是standard默认模式就会重新创建一个Activity,如果配置启动模式为singleTop,那就不会重新创建,而是回调onNewIntent()方法显示栈顶的Activity
- singleTask:不允许栈内重复,就是说一个栈内不允许有多个相同的Activity,解决不允许有多个首页问题就是把LauchMode配置为singleTask
- singleInstance:整个系统不允许重复
总结:
2、界面组件:Fragment
2.1、WHY:
- 解决碎片化的问题
- 轻量,速度快:因为Activity的创建需要走IPC,而且还有一系列和Binder、Service、ActivityManageService相关的操作,比较耗时
2.2、基本用法:
-
创建Fragment布局文件
-
创建Fragment子类,加载布局文件
-
Activity加载Fragment
- 静态加载:布局中绑定,就是在xml中绑定,把Fragment写到layout文件里面
- 动态加载:FragmentManager加载
- onAttach():Fragment和Activity建立关联时调用
- onCreateView():Fragment创建视图时调用
- onActivityCreated():Activity的onCreate()方法已返回时调用
- onDestroy():当Fragment中的视图被移除时调用
- onDetach():Fragment和Activity取消关联时调用
- 启动:onAttach()-onCreate()-onCreateView()-onActivityCreated()-onStart()-onResume()-Resumed
- 退出:Resumed-onPause()-onStop()-onDestoryView()-onDestory()-onDetach()
- 部分覆盖:Resumed-onPause()-Paused
- 部分遮挡恢复:Paused-onResume()-Resumed
- 完全覆盖:Resumed-onPause()-onStop()-onDestroyView()
- 完全遮挡恢复:onCreateView()-onActivityCreated()-onStart()-onResume()-Resumed
注:Fragment生命周期可通过FragmentTransaction.setMaxLifecycle()手动干预,就是可以设置可走到的最长生命周期是哪一个,后面的就不会走到,不过用的比较少
2.3、Fragment与Activity的交互
组件获取:
- Fragment获取Activity中的组件:getActivity().findViewById(R.id.xxx)
- Activity获取Fragment中的组件:getFragmentManager.findFragmentById(R.id.fragment_xxx)
数据传递:
-
Activity传数据给Fragment:setArgument(Bundle bundle):主要是在Activity初始化的时候传一些参数给Activity
-
Fragment传数据给Activity:
- 通过对象直接传递(方法调用(getActivity().xxx()/接口调用)
- 异步方式:通过viewModel/handler/broadcast/evenBus等通信
总结:
3、服务组件Service
3.1、基本用法:
- 注册:AndroidManifest中使用<service.../>标签
- 创建:建立相应的Service实现类
- 加载:startService()/bindService(),启动服务后不需要与用户交互的比如下载就使用startService(),启动服务后需要与用户交互的比如音乐播放器就使用bindService()
3.2、生命周期:
- onStart():服务即将启动
- onBind():跟界面组件进行绑定
- onCreate():数据初始化
- onDestory():服务销毁
3.3、Service(与Activity通信)
- 定义Binder子类,并实现getService()方法,返回Service对象
- 实现Service子类onBind()方法,返回上述Binder对象
- 实例化ServiceConnection对象,实现onServiceConnected()方法,从中获取到Service实例
- Activity中调用bindService()方法,并传递步骤3的ServiceConnection对象,将流程跑起来
- Activity可以通过调用Service实例中的方法进行直接通信
4、广播组件(Broadcast)
用于一对多的消息通知,比如网络断开、连接,系统开关机,没电
4.1、基本用法:
静态广播:
- 注册:AndroidManifest中使用<receiver.../><intent-filter.../>
- 创建:建立相应的BroadcastReceiver实现类
- 接收:在步骤2类onReceive()中接收广播
- 发送:Context.sendBroadcast()
动态广播:
注册:Context.registerReceiver()
4.2、常用系统广播
Intent.ACTION_CONNECTIVITY_CHANGE//网络连接改变
Intent.ACTION_BATTERY_CHANGE//电量改变
Intent.ACTION_SCREEN_ON//开屏
Intent.ACTION_SCREEN_OFF//息屏
Intent.ACTION_PACKAGE_INSTALL//安装应用程序
Intent.ACTION_BOOT_COMPLETED//系统启动完成
Intent.ACTION_PACKAGE_ADDED//程序已安装
Intent.ACTION_PACKAGE_REPLACED//程序更新
Intent.ACTION_PACKAGE_REMOVED//程序卸载
广播需要权限配合设置
5、数据组件:ContentProvider
5.1、基本用法:
生产者:
-
注册:AndroidManifest中使用<provider.../>
属性:authorities/exported/readPermission/writePermission
-
创建:建立相应ContentProvider实现类
方法:onCreate/getType/insert/delete/update/query
消费者:
-
声明:AndroidManifest中声明权限
-
使用:context.getContentResolver()
方法:insert/delete/update/query
6、Intent(意图)
1、Context.startActivity(Intent)
2、Context.startService(Intent)
3、Context.sendBroadcast(Intent)
eg:
6.1、基本用法
-
显示Intent
setComponent/setClass指定具体类
-
隐式Intent
Action(动作)
Data(数据)
Category(类别)
Type(数据类型)
Component(组件)
Extra(扩展信息)
Flag(标志位):比如可以利用标志位来模拟启动模式中的singleTask和singleTop,但是保证不了singleInstance
6.2、系统能力
总结:
二、通信组件
1、线程间通信-Handler
1.1、基本用法:
- 创建:新建Handler,实现handleMessage(Meassage msg)
- 构造Message:what/setData()
- 发送:子线程调用Handler.sendMessage(Message)发送Message
- 处理:在Handler的handleMessage(Message msg)主线程更新UI
2、进程间通信-Binder
Binder数据拷贝次数少一点,效率高
2.1、为何不用共享内存
因为Linux的进程隔离,就是说进程1和进程2的内存空间是独立的,只能用内核空间
2.2基本用法:(CS结构)
服务端(Service):
- 定义一个AIDL文件
- 实现描述的接口,编写service
- 如果有实体类,需要提供实体类(jar包形式)
客户端(Client):
- 拿到AIDL文件
- 绑定服务,获得接口持有对象
2.3、核心原理
eg:app的启动
总结:
本课总结:
\