Android基础第四天 | 青训营笔记

165 阅读7分钟

这是我参与「第四届青训营 」笔记创作活动的的第4天

数据存储 & 网络通信

课程回顾 → Android的常规 & 高级UI编程

1. UI组件:View & ViewGroup

2. 布局:LinearLayout 、 RelativeLayout 、 FrameLayout 、 ConstraintLayout

3. 绘制:布局加载 、 布局解析 、 UI渲染

4. 交互:获取View实例、常用交互事件 、 触摸事件 、 事件分发

5. 动画:帧动画 、 补间动画 、 属性动画

6. 自定义View:创建View 、 处理布局 、 绘制、交互 、 动画

01 网络通信

App内容的获取,都是通过网络请求。

1.1 网络请求框架对比

image.png

1.2 Retrofit介绍

Retrofit是目前Android平台上,可以说是最热门的网络请求封装框架是对OkHttp的一个封装。

1.3 Retrofit快速使用

1.3.1 Retrofit库的引入
1.3.2 创建用于描述网络请求的接口
1.3.3 使用Retrofit实例发起网络请求

1.4 Retrofit使用介绍

接口:xxxx/users/{uid}/name

类型:get请求

  1. 在需要用到Retrofit的接口的module中,新增依赖:

GitHub官方仓库查看最新版本

image.png

引入

image.png

  1. 创建用于描述网络请求的接口

image.png

定义说明:

  • 接口类名:可自定义,尽量和这类请求的含义相关

  • 函数名:可自定义,需要能识别出该接口的作用,该interface里可以增加多个不同的函数

  • @GET 注解:用于指定该接口的相对路径,并采用Get方法发起请求

  • @Path 注解:需要外部调用时,传入一个uid,该uid会替换@GET注解里相对路径的{uid}

  • 返回值Call:·返回值Call:这里用ResponseBody,可以直接拿到请求的String内容如果要自动转为Model类,例如User,这里直接替换为User就好。

  1. 发起网络请求
  • 3.1 创建Retrofit实例
  • 3.2 创建请求接口的实例,并获取到Call实例
  • 3.3 调用call.enqueue进行异步请求
  • 3.4 处理返回的数据

image.png

1.5 注解类型

image.png

1.6 字节跳动用的网络库 Cronet

Cronet与OkHttp的区别:

image.png

1.6.1 字节跳动的网络库:TTNet

优点:

  • 基于Retrofit改造,具备了Retrofit所具有的优点

  • 支持多个Http网络库的动态切换(okhttp和cronet)

  • 支持网络拦截配置:添加公共参数、动态切换协议及Host 、动态选路等

  • 支持流解析,json序列化

1.6.2 Retrofit 与 TTNet 简单用法对比

image.png

image.png

1.7 注解介绍

由于Retrofit用到了非常多的注解,这里先做个知识普及注解,也可以理解为是一个标签,这个标签可以加在类、方法、参数、成员变量上,并且可在合适的时机读取注解的内容,进行处理。

@Overrride:标注一个方法是重写了父类的实现

@Nullable:标注所描述对象有可能为空

有定义和使用注解的地方,肯定还需要有获取注解并处理注解内容的地方,不然这个注解也就没什么用了。

1.7.1 注解的处理 —— 3个时机

3个时机 → 注解的生命周期@Retention

  1. SOURCE:只有在源码中有效,编译时抛弃。例如:@Override

  2. CLASS:编译class文件时有效,一般会使用到注解处理器。

  3. RUNTIME:在运行期间,获取对应的注解,并做相关的处理。

1.7.2 Retrofit注解 @GET定义

image.png

@Target:指定作用的对象,这里是个METHOD,说明这个注解是作用在方法上,其他枚举值:

  • PARAMETER:参数

  • FIELD:类成员

  • ...

@Retention:指定注解的生命周期,这里是RUNTIME,说明这个注解要保留到运行时。

1.7.3 注解的获取和使用

通过反射获取到Method对象后,有以下一些接口来获取注解类型:

  1. Method.getGenericReturnType()获取返回类型

  2. Method.getAnnotations()获取方法的注解

  3. Method.getParameterAnnotations()获取参数注解

image.png

1.7.3 Retrofit的注解介绍

Retrofit是在运行期间,配合Java动态代理,获取方法和参数的注解,并构造Request对象。

java动态代理:Proxy.newProxyInstance

  • 利用Java的反射技术(Java Reflection),代理某个interface,一旦调用interiace里的某个方法时,实际通过代理调用InvocationHandler的invoke方法。

  • 通过Method对象,就可调用Method.getAnnotations()Method.getParameterAnnotations()来获取该方法和方法参数的注解内容。

image.png

image.png

image.png

1.8 Retrofit主流程

image.png

  1. 通过Builder模式,创建RetrofitConfig,保存baseUrl等内容。

  2. 创建动态代理对象

  3. 创建OkHttpCall

  4. 发起网络请求

1.8.1 Retrofit调用OkHttp

image.png

1.8.2 Retrofit里OkHttpClient创建时机

image.png

Retrofit构建行数中,如果未指定callFactory , 则会自动创建一个OKHttpClient

image.png

创建好的OKHttpClient将会保存在Retrofit实例中。

ExecutorCallAdapterFactory主要是用来控制Retrofit在子线程触发请求,在主线程回调结果。

1.8.3 OkHttpCall的创建

image.png

通过代理对象调用接口方法IUserInfoService#getUserName()时,会触发InvocationHandler#invoke方法。

1.9 TTNet类图设计

image.png

  1. 替换底层用到的OkHttpClient

  2. 替换底层用到的OkHttpCall

1.10 TTNet主流程

image.png

1.11 网络通信总结

image.png

02 数据存储

2.1 存储方式对比

持久性的本地数据存储是Android中常见的能力,可以在应用被杀死的情况下,而保持数据不会被清除。可以根据不同场景的诉求,可以选用不同的存储方式,常见的数据存储主要有以下4种。

image.png

2.2 数据库 —— 框架对比

image.png

2.3 Room介绍和实践案例

2.3.1 Room简介

Room是Google Jetpack家族里的一员,Room在 SQLite 上提供了一个抽象层,以便在充分利用SQLite的强大功能的同时,能够流畅地访问数据库。

2.3.2 Room主要的3个组件

image.png

  1. 数据库类(Database),用于保存数据库并作为应用持久性数据底层连接的主要访问点。

  2. 数据实体(Enity),用于表示应用的数据库中的表。

  3. 数据访问对象(DAO),提供应用可用于查询、更新、插入和删除数据库中的数据的方法。

2.3.3 Room 实践案例
  1. Room接入

Gradle目录的build.gradle文件里添加:

image.png

  1. 数据表设计

image.png

3个字段

  1. 新建Enity:定义一个User数据实体,User的每个实例都代表App数据库中的user表的一行

image.png

1.所有的属性必须是public、或者有get、set方法。 2. @PrimaryKey:表示单个主键,当主键值为null且autoGenerate为true时可以帮助自动生成键值。 3. @ColumnInfo:列名的注解

  1. 新增DAO:定义一个名为UserDao的DAO,用来对User表进行增删改查。

image.png

  1. 新建数据库类,进行数据库配置。

5.1 新增一个RoomDatabase的abstract子类

5.2 子类需加注解@Database(enity = [xxx],version = n),enities包含数据实体,将会在这这个数据库中创建对应的表,version是数据的版本号。

5.3 对于与数据库关联的每个DAO类,数据库类必须定义一个无参的抽象方法,并返回DAO类实例。

image.png

  1. 获取dao对象,既可进行数据库的增删改查操作。

image.png

2.4 Room原理介绍

核心:

1.编译期,通过kapt处理@Dao、@Database注解,动态生成对应的实现类

  1. 底层使用Android提供的SupportSQLiteOpenHelper实现数据库的增删改查等操作。
2.4.1 kapt注解处理

Room在编译期,通过kapt处理@Dao和@Database注解,生成DAO和Database的实现类。

AppDatabase --> AppDatabase_Impl UserDao-->UserDao_Impl

kapt生成的代码在build/generated/source/kapt

image.png

AppDatabase_Impl:数据库实例的具体实现,自动生成:

  • createOpenHelper(): Room.databaseBuilder().build()创建Database时,会调用实现类的createOpenHelper()创建SupportSQLiteOpenHelper,此Helper用来创建DB以及管理版本

  • userDao():创建UserDao_Impl

AppDatabase_Impl的2个具体实现:

  1. createOpenHelper()

  2. userDao()

UserDao_Impl:UserDao的具体实现,自动生成,主要有以下3个成员变量以及UserDao里定义的接口。

3个核心的成员变量:

  • _db : RoomDatabase的实例

  • _insertionAdapterOfUser : EntityInsertionAdapterd实例,用于数据insert

  • _deletionAdapterOfUser: EntityDeletionOrUpdateAdapter实例,用于数据的update/delete

n 个是UserDao里自己定义的接口的具体实现:

  • insertAll()

  • delete()

  • getAll()

  • loadAllByIds()

  • findByNames()

image.png

UserDao_Impl#insertAll(): 使用_db开启事务, 使用_insertionAdapterOfUser执行插入操作

image.png

UserDao_Impl#delete(): 使用_db开启事务, 使用_deletionAdapterOfUser执行删除操作

image.png

UserDao_Impl#getAll(): 1.自动生成sql语句 "SELECT * FROM USER” 2.获取到数据库的 Cursor光标 3.使用Cursor循环读取数据库的每条记录 4.将Cursor里的内容,读取出来, 并保存在List中返回

image.png

2.5 数据存储总结

image.png

相关资料:

  1. Retrofit官网:github.com/square/retr…

  2. Android开发者文档——Room的使用:developer.android.com/training/da…