这是我参与「第四届青训营」笔记创作活动的第2天
1. 什么是程序
开发者视角:
what 代码+资源
why 改变世界
how 知识
用户视角:
what 界面/互动/记忆
why 工具/视频/游戏
how:应用商店/搜索引擎/官网下载/三方引流
2. 安卓基础组件
1.1 界面组件: Activity & Fragment
what: Activity是界面容器
why: 前台交互 程序入口 布局容器
how:
1.1.1 Activity
Example: 实现一个图片浏览器
① 实现一个图片浏览app(activity+fragment)
相机列表页(GridView+Adaptor)
相机图片页(GridView+Adaptor)
大图浏览页(ViewPage+Adaptor)
② 旋转屏幕场景(activity生命周期)
③ 内置升级能力(service使用)
④ 单一首页(single task)
⑤ 相关图片(single top)
⑥ 扫描所有图片(contentprovider)
⑦提供图片选择能力给系统(intent)
1.1.1.1 基本用法:
① activity 是声明在AndroidManifest.xml (注册)
.ui.Mainactivity 表明默认进入MainActivity
② 设置布局文件(activity_main.xml):
③ 绑定:
1.1.1.2 Activity 生命周期
- onCreate(): 创建时回调 一般在此处创建视图和绑定数据
- onStart(): 已启动,即将进入前台 (界面还是不可见的)
- onResume(): 与用户开始交互,位于activity栈顶
- onPause(): activity失去焦点或已暂停,activity界面部分可见,下一个生命周期是onResume()/onStop() 用户还是可见的
- onStop(): activity 不再可见 下一个回调是onRestart()或onDestroy()
- onRestart(): 重启已停止的activity 下一个回调是onStart()
- onDestory(): 销毁activity 释放该activity的所有资源
- onSaveInstanceState(): 在非正常关闭时回调,用于保存数据,不支持持久化数据
- onRestoreInstanceState()/ onCreate(): 用于恢复数据
△ 有的时候app退出不一定能走到onDestroy那一步
如果想记录用户使用时长:从onResume用户能看到界面开始记录,兼容安卓4.0需要在onPause记录,更高版本安卓可以在onstop结束计时
△ 配置改变也可以不重建activity
需要到AndroidManifest里配置Activity节点的configChange属性
比如:local(语言改变)/font/orientation(旋转屏幕)/keyboardHidden(键盘显示隐藏)时都可以不重建activity
△ 解决接电话crash问题
- 产生原因:页面回收导致本地变量被置空
- 解决:
添加判空逻辑或者
在onSaveInstanceState()写入要保存的数据,在onRestoreInstanceState()恢复数据
△ 在某个页面加入主页按钮
- 问题:点击页面当前页面栈加入新首页,返回后首页会消失
- 预期:点击首页按钮回到首页 上面的页面全部退出 (正常交互)
- 解决:将首页launchmode设置为singletask
1.1.1.3 Activity 启动模式
standard:默认模式 每次打开一个页面加入栈顶 页面允许重复
single Top:不允许连续重复(回调onNewIntent())
single Task:不允许同一个栈内重复 (回调onNewIntent())
single Instance:整个系统不允许重复
△ 每一个页面都得是activity嘛?
- 不一定嗷 可以是fragment
1.1.2 Fragment
设计activity是为了解决碎片化,速度快,可以方便界面分离
1.1.2.1 Fragment基本用法:
① 创建Fragment布局文件
② 创建Fragment子类,加载布局文件
③ activity加载fragment:
静态加载:布局中绑定
动态加载:fragmentmanager加载
1.1.2.2 生命周期
- onAttach() Fragment和Activity建立关联时调用
- onCreateView() 当fragment创建视图时调用
- onActivityCreated() activity的onCreate()方法已返回时调用
- onDestroyView() 当fragment中的视图被移除时调用
- onDetach: Fragment和activity取消关联时调用
1.2.2.3 与Activity交互
组件获取
1. Fragment获取activity中的组件:getActivity().findViewById(R.ID.XXX) [getActivity有可能为空得先绑定]
2. Activity获取fragment中的组件:getFragmentManger.findFragmentById(R.if.fragment_xxx)
数据传递
1. activity传输给fragment:setArguments(Bundle bundle)
2. Fragment传输给activity:
① 通过对象直接传递(方法调用/接口调用)
② 通过viewmodel/handler/broadcast/eventbus等通信
1.2 服务组件: Service
1.3.1 基本用法:
- 注册:AndroidManifest中使用<service .../>标签
- 创建:建立相应的service实现类
- 加载:startService()/bindService()
1.3.2 生命周期:
- onStart():启动服务
- onBind()
- onCreate(): 进行初始化
- onDestroy()
1.3.3 与activity通信:
- 定义binder子类,并实现getService()方法,返回service对象
- 实现service类onBind()方法,返回上述binder对象
- 实例化serviceconnection对象,实现onServiceConnected()方法,从中获取到service实例
- activity 中调用bindService()方法,并传递步骤三ServiceConnection对象,将流程跑起来
- activity既可以通过调用service实例中的方法进行直接通信
1.3 广播组件: Broadcast
1.3.1 基本用法
静态广播:
- 注册:AndroidManifest中使用<receiver.../><intent-filter.../>
- 创建:建立相应的broadcastReceiver实现类
- 接收:在步骤2类onReceive()中接收广播
- 发送:context.sendBroadcast()
动态广播:
- 注册: Content.registerReceiver()
1.3.2 常用系统广播
Intent.Action_CONNECTIVITY_CHANGE
Intent.Action_BATTERY_CHANGED
Intent.Action_SCREEN_ON
Intent.Action_SCREEN_OFF
Intent.Action_PACKAGE_INSTALL
Intent.Action_BOOT_COMPLETED
Intent.Action_PACKAGE_ADDED
Intent.Action_PACKAGE_REPLACED/REMOVED
1.4 数据组件: ContentProvider & ContentResolver
(使用系统东西 eg: 系统图库 才会用)
1.4.1 基本用法
生产者:
- 注册:AndroidManifest中使用<provider .../>
属性: authories/exported/readPermission/writePermission
- 创建: 建立相应的ContentProvider实现类
方法: onCreate/getType/insert/delete/update/query
消费者:
- 声明:AndroidManifest中声明权限
- 使用:context.getContentResolver()
方法:insert/delete/update/query
1.5 意图组件: Intent
你想干什么事情 有什么需求 系统对这个需求进行处理
Context.startActivity(Intent)
Context. startService(Intent)
Context.sendBroadcast(Intent)
1.5.1 基本用法
显式intent:setComponent/setClass指定具体类
隐式intent:action(动作), data(数据), category(类别),type(数据类型),component(组件),extra(扩展信息),flag(标志位)
1.5.2 Intent (系统能力)
电话:Intent (Intent.ACTION_DIAL, Uri.parse("tel:10010"))
短信:Intent (Intent.ACTION_SENDTO, Uri.parse("smsto: 10010"))
使用:startActivity(intent)
3. 安卓通信组件
1. Handler
处理主线程之间的通信
如果想对界面进行更新/界面属性 只能在主线程操作
主线程很宝贵qvq 耗时操作放在子线程
原理:消息队列
1.1 基本用法
- 创建:新建Handler,实现handleMessage(Message)
- 构造Message:what/setData()
- 发送:子线程调用Handler.sendMessage(Message) 发送Message
- 处理:在Handler的handleMessage(Message msg) 主线程更新UI
2. Binder
进程之间的通信:只需要一次内存交换
2.1 基本用法
服务端:
1. 定义一个AIDL文件
2. 实现描述的接口,编写service
3. 如果有实体类,需要提供实体类(jar包形式)
客户端:
1. 拿到AIDL文件
2. 绑定服务,获得接口持有对象
2.2 核心原理
匿名共享内存 Binder驱动 ServiceManager