• Android基础第四天 | 字节跳动第四届青训营笔记


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

    数据存储 & 网络通信

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

    1. UI组件:View & ViewGroup

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

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

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

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

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

    01 网络通信

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

    1.1 网络请求框架对比

    在这里插入图片描述

    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官方仓库查看最新版本

    在这里插入图片描述

    引入

    在这里插入图片描述

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

    在这里插入图片描述

    定义说明:

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

    • 函数名:可自定义,需要能识别出该接口的作用,该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 处理返回的数据

    在这里插入图片描述

    1.5 注解类型

    在这里插入图片描述

    1.6 字节跳动用的网络库 Cronet

    Cronet与OkHttp的区别:

    在这里插入图片描述

    1.6.1 字节跳动的网络库:TTNet

    优点:

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

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

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

    • 支持流解析,json序列化

    1.6.2 Retrofit 与 TTNet 简单用法对比

    在这里插入图片描述

    在这里插入图片描述

    1.7 注解介绍

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

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

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

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

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

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

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

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

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

    1.7.2 Retrofit注解 @GET定义

    在这里插入图片描述

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

    • PARAMETER:参数

    • FIELD:类成员

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

    1.7.3 注解的获取和使用

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

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

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

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

    在这里插入图片描述

    1.7.3 Retrofit的注解介绍

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

    java动态代理:Proxy.newProxyInstance

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

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

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    1.8 Retrofit主流程

    在这里插入图片描述

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

    2. 创建动态代理对象

    3. 创建OkHttpCall

    4. 发起网络请求

    1.8.1 Retrofit调用OkHttp

    在这里插入图片描述

    1.8.2 Retrofit里OkHttpClient创建时机

    在这里插入图片描述

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

    在这里插入图片描述

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

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

    1.8.3 OkHttpCall的创建

    在这里插入图片描述

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

    1.9 TTNet类图设计

    在这里插入图片描述

    1. 替换底层用到的OkHttpClient

    2. 替换底层用到的OkHttpCall

    1.10 TTNet主流程

    在这里插入图片描述

    1.11 网络通信总结

    在这里插入图片描述

    02 数据存储

    2.1 存储方式对比

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

    在这里插入图片描述

    2.2 数据库 —— 框架对比

    在这里插入图片描述

    2.3 Room介绍和实践案例

    2.3.1 Room简介

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

    2.3.2 Room主要的3个组件

    在这里插入图片描述

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

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

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

    2.3.3 Room 实践案例
    1. Room接入

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

    在这里插入图片描述

    1. 数据表设计

    在这里插入图片描述

    3个字段

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

    在这里插入图片描述

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

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

    在这里插入图片描述

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

    5.1 新增一个RoomDatabase的abstract子类

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

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

    在这里插入图片描述

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

    在这里插入图片描述

    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

    在这里插入图片描述

    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()

    在这里插入图片描述

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

    在这里插入图片描述

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

    在这里插入图片描述

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

    在这里插入图片描述

    2.5 数据存储总结

    在这里插入图片描述

    相关资料:

    1. Retrofit官网:https://github.com/square/retrofit

    2. Android开发者文档——Room的使用:https://developer.android.com/training/data-storage/room?hl=zh-cn

  • 相关阅读:
    【Docker】03-安装redis
    JAVA 从入门到起飞 day8 面向对象01
    教程三 在Go中使用Energy创建跨平台应用 - 状态控制
    YOLOv8改进实战 | 更换主干网络Backbone之轻量化模型Efficientvit
    uniapp map地图实现marker聚合点,并点击marker触发事件
    记录一下MySql update会锁定哪些范围的数据
    阿里云SLB负载均衡&&ESS弹性伸缩
    基于matlab目标雷达横截面建模(附源码)
    x64 简介
    【有趣的Python小程序】Python多个简单上手的库制作WalkLattice 走格子游戏 (思路篇)上
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/126152567