Paging概述
1 | Paging 库可帮助您加载和显示来自本地存储或网络中更大的数据集中的数据页面。此方法可让您的应用更高效地利用网络带宽和系统资源; |
使用 Paging 库的优势
1 | - 分页数据的内存中缓存。该功能有助于确保您的应用在处理分页数据时高效使用系统资源。 |
1 | implementation 'androidx.paging:paging-runtime:2.1.0' |
//没有认真研究,写真实项目时再认真学习下,以下是简单的使用案例,真实项目可能不一样
1 | /** |
1 |
|
1 |
|
Paging概述
1 | Paging 库可帮助您加载和显示来自本地存储或网络中更大的数据集中的数据页面。此方法可让您的应用更高效地利用网络带宽和系统资源; |
使用 Paging 库的优势
1 | - 分页数据的内存中缓存。该功能有助于确保您的应用在处理分页数据时高效使用系统资源。 |
1 | implementation 'androidx.paging:paging-runtime:2.1.0' |
//没有认真研究,写真实项目时再认真学习下,以下是简单的使用案例,真实项目可能不一样
1 | /** |
1 |
|
1 |
|
HILT 是什么
1 | Hilt 提供了一种合并 Dagger 的标准方法 依赖项注入到 Android 应用程序中。 |
添加依赖项
1 | //1. 配置Hilt的插件路径(project->build.gradle) |
Hilt 目前支持以下 Android 类:
1 | 1.Application |
最简单的使用
1 | 1.提供一个对象 |
-为接口注入实例
1 | //1 |
HILT 常用的注解的含义
1 | @HiltAndroidApp |
Room是什么?
1 | Room 是一个轻量级 orm 数据库,本质上是一个SQLite抽象层,但是使用起来会更加简单,类似于Retrofit库。Room 在开发阶段通过注解 |
ORM映射关系设计与详解
1 | 对象关系映射(英语:Object Relational Mapping,简称ORM,或0/RM,或0/R mapping),是一种程序设计技术,用于实现面向对象编程 |
Room使用:
1 | implementation "androidx.room:room-runtime:2.2.3" |
1 | 官网的文档也指出,我们需要创建这三个文件,才能正式的使用Room: |
1.定义Entity:
1 | /** |
2.定义 Dao:
DAO类主要是提供对数据库的访问方法,是一个接口类
。通过将SQL语句与方法结合的方式,降低结构的复杂程度。
1 | /** |
3.Room Database类构建
得益于Room的良好封装,这个类的构建步骤只有两步,非常的简单。
1 | /** |
这样就完成了对RoomDatabase的构建,这里要注意引入@Database
注解,它表明需要与哪一个Entity类产生联系,生成对应的数据库表。并且version
版本号是一个必填字段,在这里,我们定义为1即可。
4.在Activity中操作Room
这里要特别注意的是:虽然Room可以通过调用.allowMainThreadQueries()方法允许在主线程中进行查询,但是实际操作中禁止在主线程操作数据库,避免出现ANR问题。需要开启子线程进行数据的操作!
1 | public class RoomActivity extends AppCompatActivity { |
什么是ViewModel
1 | 它是介于View(视图)和Model(数据模型)之间的一个东西。它起到了桥梁的作用,使视图和数据既能分离,也能保持通信。即ViewModel |
ViewModel的特性
1 | 1.数据持久化 |
1.依赖库
1 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' |
2.使用
1 | //1.model类 |
什么是Dagger2
1 | Dagger 2是由Google开发的 依赖注入框架,它利用Java和Java注解处理器的强大功能,提供了一种优雅的方式来进行依赖注入。 |
dagger2 简单理解
1 | 1.一般我们使用一个实体类或者工具或者请求,比如在MainActivity中使用UerInfo.class,我们会在new Userinfo(),去使用 |
dagger2 的使用
1.在build.gradle中引入插件
1 | // dagger2 的功能支持 |
2.简单使用:
1 | //1.HttpObject 对象-->快递 |
3.dagger2 单例使用
1 | 1.局域单例:存在于当前类中,只有一个实例,需要增加一个单例注解 @Singleton。 |
局域单例示例:(在moudle和Component类中添加@Singleton注解)
1 | //1.moudle |
全局单例示例:(在moudle和Component类中添加@Singleton注解)
1 | //1.Component中添加次级要调用的类 |
4.多个Component组合依赖
dagger2不能使用多个Component同时注入同一个类中 这种情况需要进行Component的组合;
先确定使用哪个 Component 作为主 Component,确定后,主 Component 仍然执行注入操作,而其他 Component 作为依赖项,不再执行注入,转而提供 Module 提供的对象。一般我们会选择 ApplicationComponent 作为主 Component。
1 | //1.新建一个对象DataObject |
假如现在有个需求,想让 DataObject 也变成个单例对象,按照我们之前的做法,给 PresenterModule 中的 Provides 方法和 PresenterComponent 加上 @Singleton 之后,会发现编译报错了:
1 | com.demo.dagger.component.ApplicationComponent also has @Singleton |
它说 ApplicationComponent 中已经有 @Singleton 了。显然,Dagger2 要求 @Singleton 不能用在多个组件上。
1 | 使用 @Scope 的原则: |
@Scope 注解表示作用域,被其修饰的类或提供对象的方法会被做成单例,所以我们可以用 @Scope 自定义一个作用域注解:
1 | @Scope |
实际上它和 @Singleton 一样只是名字不同:
1 | @Scope |
以下示例编译报错,未查明原因
Component使用
1 | @MyScope |
moudle使用
1 | @Module |
什么是DataBinding
1 | DataBinding 是谷歌官方发布的一个框架,顾名思义即为数据绑定,是 MVVM 模式在 Android 上的一种实现,用于降低布局和逻辑的 |
启用 DataBinding 的方法是在对应 Model 的 build.gradle 文件里加入以下代码,同步后就能引入对 DataBinding 的支持
1 | android { |
简单使用
启用 DataBinding 后,这里先来看下如何在布局文件中绑定指定的变量
打开布局文件,选中根布局的 ViewGroup,按住 Alt + 回车键,点击 “Convert to data binding layout”,就可以生成 DataBinding 需要的布局规则
这里先来声明一个 Modle
1 | public class User { |
和原始布局的区别在于多出了一个 layout 标签将原布局包裹了起来,data 标签用于声明要用到的变量以及变量类型,要实现 MVVM 的 ViewModel 就需要把数据(Model)与 UI(View)进行绑定,data 标签的作用就像一个桥梁搭建了 View 和 Model 之间的通道
1 | <?xml version="1.0" encoding="utf-8"?> |
通过 @{viewModel.name}
使 TextView 引用到相关的变量,DataBinding 会将之映射到相应的 getter 方法 之后可以在 Activity 中通过 DataBindingUtil
设置布局文件,省略原先 Activity 的 setContentView()
方法,并为变量 userInfo 赋值
如果 User 类型要多处用到,也可以直接将之 import 进来,这样就不用每次都指明整个包名路径了,而 java.lang.*
包中的类会被自动导入,所以可以直接使用
1 | <data> |
由于 @{user.name}
在布局文件中并没有明确的值,所以在预览视图中什么都不会显示,不便于观察文本的大小和字体颜色等属性,此时可以为之设定默认值(文本内容或者是字体大小等属性都适用),默认值将只在预览视图中显示,且默认值不能包含引号
1 | android:text="@{user.name,default=defaultValue}" |
在 Activity 中通过 DataBindingUtil
设置布局文件,省略原先 Activity 的 setContentView()
方法,并为变量 userInfo 赋值
1 | public class DataBindingActivity extends AppCompatActivity { |
此外,也可以通过 ActivityMain2Binding 直接获取到指定 ID 的控件
1 | binding.tv1.setText("tyl"); |
Databinding 同样是支持在 Fragment 和 RecyclerView 中使用 。例如,可以看 Databinding 在 Fragment 中的使用
1 | @Override |
以上实现数据绑定的方式,每当绑定的变量发生变化的时候,都需要重新向 ViewDataBinding 传递新的变量值才能刷新 UI 。接下来看如何实现自动刷新 UI
驱动 UI 刷新
实现数据变化自动驱动 UI 刷新的方式有三种:BaseObservable
、ObservableField
、ObservableCollection
BaseObservable
一个纯净的 ViewModel 类被更新后,并不会让 UI 自动更新。而数据绑定后,我们自然会希望数据变更后 UI 会即时刷新,Observable 就是为此而生的概念
BaseObservable 提供了 notifyChange() 和 notifyPropertyChanged() 两个方法,前者会刷新所有的值域,后者则只更新对应 BR 的 flag,该 BR 的生成通过注释 @Bindable 生成,可以通过 BR notify 特定属性关联的视图
1 | public class User extends BaseObservable { |
在 setName() 方法中更新的只是本字段,而 setPwd() 方法中更新的是所有字段
MyJetpackStudy: jetpack学习 (gitee.com)
1.什么是LiveData
1 | LiveData是Jetpack组件的一部分,更多的时候是搭配ViewModel来使用,相对于Observable,LiveData的最大优势是其具有生命感知的, |
LiveData的优点
1 | 1.确保界面符合数据状态 |
使用 LiveData 对象
1 | 请按照以下步骤使用LiveData对象: |
LiveData的使用
常用方法:
方法名 | 作用 |
---|---|
setValue(T value): | 设置 LiveData 的值,并通知所有活跃的观察者进行更新。此方法应在主线程中调用 |
postValue(T value) | 与setValue()类似,但可以在任何线程中调用。内部使用 Handler 来确保更新操作在主线程执行。 |
getValue() | 获取当前 LiveData 实例的值 |
observe(LifecycleOwner owner, Observer<? super T> observer) | 将观察者(Observer)添加到 LiveData。当 LiveData 的值发生变化时,会通知观察者。该方法传入一个 LifecycleOwner 对象(如 Activity 或 Fragment),LiveData 将观察者与该 LifecycleOwner 的生命周期关联起来,以自动管理观察者的注册和取消注册。 |
hasObservers() | 检查 LiveData 是否有活跃的观察者。 |
removeObserver(Observer<? super T> observer) | 从 LiveData 中移除观察者。 |
observeForever(Observer<? super T> observer) | 与 observe()类似,但观察者不会自动注销。需要手动调用 removeObserver()方法来取消观察。 |
简单示例:
1 | public class NameViewModel extends ViewModel { |
MyJetpackStudy: jetpack学习 (gitee.com)
Lifecycle是什么?
1 | lifecycle 是属于Android Jetpack(官方开发工具包)—— Architecture(架构组件)中的一员。 |
Lifecycle的特点
1 | 1.生命周期感知:Lifecycle 可以感知应用组件的生命周期状态,包括活动状态、暂停状态、停止状态等。 |
Lifecycle使用
1.先看看可以引用哪些?
1 | //androidx |
1 | //非androidx |
除了Activity和Fragment外,还可以绑定Service和Application的生命周期。只要引入支持相关的可选库即可;官方提到最多的是Activity和Fragment,是因为平时主要用于这两个组件;其实只要有生命周期的组件都可以跟它绑定。而在Android中大多数的组件都是有生命周期的。
2.简单使用案例:
1 | package com.example.lifecycledemo1; |
工具类封装:
1 | //使用:被观察者继承BaseActivity或者添加getLifecycle().addObserver(new BaseLifeCycle());即可 |
Wine介绍:
1 | Wine是一个允许在Linux和其他类Unix操作系统上运行Windows应用程序的兼容层。它通过将Windows API转换为本地系统调用来实现这 |
安装 Wine 方法:
1 | 1、如果您使用的是 64 位系统,请开启 32 bit 架构支持(如果您之前没有开启的话): |
安装winetricks
1 | 1.在软件商城里面搜索安装winetricks。安装后在终端输入winetricks,会打开图形界面设置。 |
字体乱码
1 | winetricks上可以安装字体。也可手动将 Windows 下面的字体复制到~/.wine/drive_c/windows/Fonts/ 。 |
安装/卸载软件
1 | 安装:在exe文件目录,执行:wine xx.exe |
wine的常用命令
1 | wine [程序名] (运行Windows程序) |
所有命令列表:
1 | 1、这些子程序通常可通过运行以下程序访问: |
这些程序直接运行(即不是“葡萄酒程序”,只是“程序”):
1 | winelauncher-尝试智能地管理使用Wine启动程序的程序。 |
工具
1 | 这些工具是帮助Wine开发的脚本和可执行文件的集合。在工具目录(例如~/wine git/tools/wineinstall)中,它们作为独立命令调用。 |
环境:android13.0.0_r6
1、SystemUI介绍
1.1、SystemUI摘要
1 | 在Android系统中SystemUI是以应用的形式运行在Android系统当中,即编译SystemUI模块会生产APK文件,源代码路径 |
1.2、什么是SystemUI
1 | 在前文1.1章节中可知,SystemUI是一个普通的APK文件,即是一个普通的APP,但是,手机使用者看见的所有SystemUI的内容都不像是 |
2、SystemUI的架构
SystemUI的整体架构:
Android SystemUI采用了MVC(Model-View-Controller)架构,以实现界面元素的管理和交互。
它由多个关键组件组成,包括状态栏、导航栏、通知管理器、快捷设置等。
各个组件的功能和相互关系:
1 | 状态栏(Status Bar):显示系统状态信息,如时间、电池电量、信号强度等,并提供快速访问通知和快捷设置的入口。 |
这些组件相互配合,构成了SystemUI的整体架构。每个组件负责不同的功能和交互,并通过事件触发和消息传递等机制相互关联。理解SystemUI的架构和组件之间的相互关系,有助于我们深入了解系统界面的实现原理,并进行自定义和扩展。
3、SystemUI的启动过程
SystemUI任何内容都不像一个APP,自然它的启动也不像大多APP一样启动一个Activity。SystemUI顾名思义就是全局UI,必须在开机过程中完成启动,并不可退出。
回顾Android系统开机的过程,会创建server进程维护系统各种服务,如下:
1 | Android系统启动流程: |
SystemUI作为系统主要进程,就是在SystemServer启动的服务其中之一
SystemServer.java
1 | public static void main(String[] args) { |
总结下代码流程:SystemServer
main()方法会调用SystemServer.run()方法,在run方法中,会启动bootStrapService,coreService,以及其他服务otherService,在startOtherServices()中,会注册AMS的systemReady回调,在回调中启动SystemUI,其实就是启动了SystemUIService。
SystemUIService.java
1 | //frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java |
SystemUIApplication.java
1 | //frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java |
SystemUIApplication.java
1 | private void startServicesIfNeeded( |
1 | <!-- SystemUI Services: The classes of the stuff to start. --> |
SystemUIService的onCreate()方法中,直接调用SystemUIApplication.startServicesIfNeeded()方法,最终会将所有服务一一加载并通过start()方法启动起来。
至此,SystemUI基本启动流程就结束了。