【Android】数据存储
本章介绍Android五种主要存储方式的用法,包括共享参数SharedPreferences、数据库SQLite、SD卡文件、App的全局内存,另外介绍重要组件之一的应用Application的基本概念与常见用法,以及四大组件之一的内容提供器ContentProvider的基本概念与常见用法。
共享参数SharedPreferences
本节介绍Android的键值对存储方式——共享参数SharedPreferences的使用方法,包括如何保存数据与读取数据,通过共享参数结合“登录App”项目实现记住密码功能。
共享参数的基本用法
SharedPreferences是Android的一个轻量级存储工具,采用的存储结构是Key-Value的键值对方式,类似于Java的Properties类,二者都是把Key-Value的键值对保存在配置文件中。不同的是Properties的文件内容是Key=Value这样的形式,而SharedPreferences的存储介质是符合XML规范的配置文件。保存SharedPreferences键值对信息的文件路径是/data/data/应用包名/shared_prefs/文件名.xml。下面是一个共享参数的XML文件示例:
基于XML格式的特点,SharedPreferences主要适用于如下场合:
(1)简单且孤立的数据。若是复杂且相互间有关的数据,则要保存在数据库中。
(2)文本形式的数据。若是二进制数据,则要保存在文件中。
(3)需要持久化存储的数据。在App退出后再次启动时,之前保存的数据仍然有效。
实际开发中,共享参数经常存储的数据有App的个性化配置信息、用户使用App的行为信息、临时需要保存的片段信息等。
SharedPreferences对数据的存储和读取操作类似于Map,也有put函数用于存储数据、get函数用于读取数据。在使用共享参数之前,要先调用getSharedPreferences函数声明文件名与操作模式,示例代码如下:
// 从share.xml中获取共享参数对象SharedPreferences shared = getSharedPreferences("share", MODE_PRIVATE);
getSharedPreferences方法的第一个参数是文件名,上面的share表示当前使用的共享参数文件名是share.xml;第二个参数是操作模式,一般都填MODE_PRIVATE,表示私有模式。
共享参数存储数据要借助于Editor类,示例代码如下:
SharedPreferences.Editor editor = shared.edit(); // 获得编辑器的对象editor.putString("name", "Mr Lee"); // 添加一个名叫name的字符串参数editor.putInt("age", 30); // 添加一个名叫age的整型参数editor.putBoolean("married", true); // 添加一个名叫married的布尔型参数editor.putFloat("weight", 100f); // 添加一个名叫weight的浮点数参数editor.commit(); // 提交编辑器中的修改
共享参数读取数据相对简单,直接使用对象即可完成数据读取方法的调用,注意get方法的第二个参数表示默认值,示例代码如下:
String name = shared.getString("name", ""); // 从共享参数中获得名叫name的字符串int age = shared.getInt("age", 0); // 从共享参数中获得名叫age的整型数boolean married = shared.getBoolean("married", false); // 从共享参数中获得名叫married的布尔数float weight = shared.getFloat("weight", 0); // 从共享参数中获得名叫weight的浮点数
数据库SQLite
本节介绍Android的数据库存储方式—— SQLite的使用方法,包括如何建表和删表、变更表结构以及对表数据进行增加、删除、修改、查询等操作,然后通过SQLite结合“登录App”项目改进记住密码功能。
SQLite是一个小巧的嵌入式数据库,使用方便、开发简单,手机上最早由iOS运用,后来Android也采用了SQLite。SQLite的多数SQL语法与Oracle一样,下面只列出不同的地方:
(1)建表时为避免重复操作,应加上IF NOT EXISTS关键词,例如CREATE TABLE IF NOT EXISTS table_name。
(2)删表时为避免重复操作,应加上IF EXISTS关键词,例如DROP TABLE IF EXISTS table_name。
(3)添加新列时使用ALTER TABLE table_name ADD COLUMN …,注意比Oracle多了一个COLUMN关键字。
(4)在SQLite中,ALTER语句每次只能添加一列,如果要添加多列,就只能分多次添加。
(5)SQLite支持整型INTEGER、字符串VARCHAR、浮点数FLOAT,但不支持布尔类型。布尔类型数要使用整型保存,如果直接保存布尔数据,在入库时SQLite就会自动将其转为0或1,0表示false,1表示true。
(6)SQLite建表时需要一个唯一标识字段,字段名为_id。每建一张新表都要例行公事加上该字段定义,具体属性定义为_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL。
(7)条件语句等号后面的字符串值要用单引号括起来,如果没用使用单引号括起来,在运行时就会报错。
SQLiteDatabase是SQLite的数据库管理类,开发者可以在活动页面代码或任何能取到Context的地方获取数据库实例,参考代码如下:
// 创建名叫test.db的数据库。数据库如果不存在就创建它,如果存在就打开它SQLiteDatabase db = openOrCreateDatabase(getFilesDir() + "/test.db", Context.MODE_PRIVATE, null);// 删除名叫test.db数据库// deleteDatabase(getFilesDir() + "/test.db");
SQLiteDatabase提供了若干操作数据表的API,常用的方法有3类,列举如下:
1. 管理类,用于数据库层面的操作。
- openDatabase:打开指定路径的数据库。
- isOpen:判断数据库是否已打开。
- close:关闭数据库。
- getVersion:获取数据库的版本号。
- setVersion:设置数据库的版本号。
2. 事务类,用于事务层面的操作。
- beginTransaction:开始事务。
- setTransactionSuccessful:设置事务的成功标志。
- endTransaction:结束事务。执行本方法时,系统会判断是否已执行setTransactionSuccessful,如果之前已设置就提交,如果没有设置就回滚。
3. 数据处理类,用于数据表层面的操作。
- execSQL:执行拼接好的SQL控制语句。一般用于建表、删表、变更表结构。
- delete:删除符合条件的记录。
- update:更新符合条件的记录。
- insert:插入一条记录。
- query:执行查询操作,返回结果集的游标。
- rawQuery:执行拼接好的SQL查询语句,返回结果集的游标。
数据库帮助器SQLiteOpenHelper
SQLiteDatabase存在局限性,例如必须小心、不能重复地打开数据库,处理数据库的升级很不方便。Android提供了一个辅助工具—— SQLiteOpenHelper,用于指导开发者进行SQLite的合理使用。
SQLiteOpenHelper的具体使用步骤如下:
步骤01 新建一个继承自SQLiteOpenHelper的数据库操作类,提示重写onCreate和onUpgrade两个方法。其中,onCreate方法只在第一次打开数据库时执行,在此可进行表结构创建的操作;onUpgrade方法在数据库版本升高时执行,因此可以在onUpgrade函数内部根据新旧版本号进行表结构变更处理。
步骤02 封装保证数据库安全的必要方法,包括获取单例对象、打开数据库连接、关闭数据库连接。
- 获取单例对象:确保App运行时数据库只被打开一次,避免重复打开引起错误。
- 打开数据库连接:SQLite有锁机制,即读锁和写锁的处理;故而数据库连接也分两种,读连接可调用SQLiteOpenHelper的getReadableDatabase方法获得,写连接可调用getWritableDatabase获得。
- 关闭数据库连接:数据库操作完毕后,应当调用SQLiteDatabase对象的close方法关闭连接。
步骤03 提供对表记录进行增加、删除、修改、查询的操作方法。
可被SQLite直接使用的数据结构是ContentValues类,类似于映射Map,提供put和get方法用来存取键值对。区别之处在于ContentValues的键只能是字符串,查看ContentValues的源码会发现其内部保存键值对的数据结构就是HashMap“private HashMap<String, Object>mValues;”。ContentValues主要用于记录增加和更新操作,即SQLiteDatabase的insert和update方法。
对于查询操作来说,使用的是另一个游标类Cursor。调用SQLiteDatabase的query和rawQuery方法时,返回的都是Cursor对象,因此获取查询结果要根据游标的指示一条一条遍历结果集合。Cursor的常用方法可分为3类,说明如下:
1. 游标控制类方法,用于指定游标的状态。
- close:关闭游标。
- isClosed:判断游标是否关闭。
- isFirst:判断游标是否在开头。
- isLast:判断游标是否在末尾。
2. 游标移动类方法,把游标移动到指定位置。
- moveToFirst:移动游标到开头。
- moveToLast:移动游标到末尾。
- moveToNext:移动游标到下一条记录。
- moveToPrevious:移动游标到上一条记录。
- move:往后移动游标若干条记录。
- moveToPosition:移动游标到指定位置的记录。
3. 获取记录类方法,可获取记录的数量、类型以及取值。
- getCount:获取结果记录的数量。
- getInt:获取指定字段的整型值。
- getFloat:获取指定字段的浮点数值。
- getString:获取指定字段的字符串值。
- getType:获取指定字段的字段类型。
SD卡文件操作
本节介绍Android的文件存储方式—— SD卡的用法,包括如何获取SD卡目录信息、公有存储空间与私有存储空间的区别、在SD卡上读写文本文件、在SD卡读写图片文件等功能。
SD卡的基本操作
手机的存储空间一般分为两块,一块用于内部存储,另一块用于外部存储(SD卡)。早期的SD卡是可插拔式的存储芯片,不过自己买的SD卡质量参差不齐,经常会影响App的正常运行,所以后来越来越多的手机把SD卡固化到手机内部,虽然拔不出来,但是Android仍然称之为外部存储。
获取手机上的SD卡信息通过Environment类实现,该类是App获取各种目录信息的工具,主要方法有以下7种。
-
getRootDirectory:获得系统根目录的路径。
-
getDataDirectory:获得系统数据目录的路径。
-
getDownloadCacheDirectory:获得下载缓存目录的路径。
-
getExternalStorageDirectory:获得外部存储(SD卡)的路径。
-
getExternalStorageState:获得SD卡的状态。
SD卡状态的具体取值说明见表4-1。
-
getStorageState:获得指定目录的状态。
-
getExternalStoragePublicDirectory:获得SD卡指定类型目录的路径。
目录类型的具体取值说明见表4-2。
为正常操作SD卡,需要在AndroidManifest.xml中声明SD卡的权限,具体代码如下:
公有存储空间与私有存储空间
本来在AndroidManifest.xml里面配置了存储空间的权限,代码就能正常读写SD卡的文件。可是Android从7.0开始加强了SD卡的权限管理,即使App声明了完整的SD卡操作权限,系统仍然默认禁止该App访问外部存储。
不过系统默认关闭存储其实只是关闭外部存储的公共空间,外部存储的私有空间依然可以正常读写。这是缘于Android把外部存储分成了两块区域,一块是所有应用均可访问的公共空间,另一块是只有应用自己才可访问的专享空间。之前讲过,内部存储保存着每个应用的安装目录,但是安装目录的空间是很紧张的,所以Android在SD卡的“Android/data”目录下给每个应用又单独建了一个文件目录,用于给应用保存自己需要处理的临时文件。这个给每个应用单独建立的文件目录,只有当前应用才能够读写文件,其他应用是不允许进行读写的,故而“Android/data”目录算是外部存储上的私有空间。这个私有空间本身已经做了访问权限控制,因此它不受系统禁止访问的影响,应用操作自己的文件目录就不成问题了。当然,因为私有的文件目录只有属主应用才能访问,所以一旦属主应用被用户卸载,那么对应的文件目录也会一起被清理掉。
既然外部存储分成了公共空间和私有空间两部分,这两部分空间的路径获取也就有所不同。获取公共空间的存储路径,调用的是Environment.getExternalStoragePublicDirectory方法;获取应用私有空间的存储路径,调用的是getExternalFilesDir方法。下面是分别获取两个空间路径的代码例子:
应用的私有空间路径位于“外部存储根目录/Android/data/应用包名/files/Download”这个目录之下。
文本文件读写
文本文件的读写一般借助于FileOutputStream和FileInputStream。其中,FileOutputStream用于写文件,FileInputStream用于读文件。文件输出输入流是Java语言的基础工具,这里不再赘述,直接给出具体的实现代码:
图片文件读写
Android的图片处理类是Bitmap,App读写Bitmap可以使用FileOutputStream和FileInputStream。不过在实际开发中,读写图片文件一般用性能更好的BufferedOutputStream和BufferedInputStream。
保存图片文件时用到Bitmap的compress方法,可指定图片类型和压缩质量;打开图片文件时使用BitmapFactory的decodeStream方法。读写图片的具体代码如下:
应用Application基础
本节介绍Android重要组件Application的基本概念和常见用法。首先说明Application的生命周期,接着利用Application的持久特性实现App内部全局内存中的数据保存和获取。
Application的生命周期
Application是Android的一大组件,在App运行过程中有且仅有一个Application对象贯穿整个生命周期。打开AndroidManifest.xml时会发现activity节点的上级正是application节点,只是默认的application节点没有指定name属性,不像activity节点默认指定name属性值为.MainActivity,让人知晓这个activity的入口代码是MainActivity.java。现在试试给application节点加上name属性,看看其庐山真面目。
(1)打开AndroidManifest.xml,给application节点加上name属性,表示application的入口代码是MainApplication.java。
android:name=".MainApplication"
(2)创建MainApplication类,该类继承自Application,可以重写的方法主要有以下4个。
- Create:在App启动时调用。
- onTerminate:在App退出时调用(按字面意思)。
- onLowMemory:在低内存时调用。
- onConfigurationChanged:在配置改变时调用,例如从竖屏变为横屏。
(3)运行App,同时开启日志的打印。但是只在一开始看到MainApplication的onCreate操作(先于Activity的onCreate),却始终无法看到它的onTerminate操作,无论是自行退出还是强行杀死App的进程,日志都不会打印onTerminate。想在App退出前做资源回收操作,那么千万不要放在onTerminate方法中。
利用Application操作全局变量
C/C++有全局变量,因为全局变量保存在内存中,所以操作全局变量就是操作内存,内存的读写速度远比读写数据库或读写文件快得多。全局的意思是其他代码都可以引用该变量,因此全局变量是共享数据和消息传递的好帮手。不过,Java没有全局变量的概念。与之比较接近的是类里面的静态成员变量,该变量可被外部直接引用,并且在不同地方引用的值是一样的(前提是在引用期间不能修改该变量的值),所以可以借助静态成员变量实现类似全局变量的功能。
前面花费很大功夫介绍Application的生命周期,目的是说明其生命周期覆盖App运行的全过程。不像短暂的Activity生命周期,只要进入别的页面,原页面就被停止或销毁。因此,通过利用Application的持久存在性可以在Application对象中保存全局变量。
适合在Application中保存的全局变量主要有下面3类数据:
(1)会频繁读取的信息,如用户名、手机号等。
(2)从网络上获取的临时数据,为节约流量、减少用户等待时间,想暂时放在内存中供下次使用,如logo、商品图片等。
(3)容易因频繁分配内存而导致内存泄漏的对象,如Handler对象等。
要想通过Application实现全局内存的读写,得完成以下3项工作:
(1)写一个继承自Application的类MainApplication。该类要采用单例模式,内部声明自身类的一个静态成员对象,在创建App时把自身赋值给这个静态对象,然后提供该静态对象的获取方法getInstance。
(2)在Activity中调用MainApplication的getInstance方法,获得MainApplication的一个静态对象,通过该对象访问MainApplication的公共变量和公共方法。
(3)不要忘了在AndroidManifest.xml中注册新定义的Application类名,即在application节点中增加android:name属性,值为.MainApplication。
App把注册信息保存到MainApplication的全局变量中,然后在另一个页面从MainApplication的全局变量中读取保存好的注册信息。
完成以上编码后,Activity页面代码即可直接通过MainApplication.getInstance().mInfoMap对全局变量进行增、删、改、查操作。
内容提供与处理
本节介绍Android四大组件之一的ContentProvider的基本概念和常见用法。首先说明如何使用内容提供器封装数据的外部访问接口;接着阐述如何通过内容解析器在外部查询和修改数据,以及使用内容操作器完成批量数据操作;然后说明内容观察器的应用场合,并演示如何借助内容观察器实现流量校准的功能。
内容提供器ContentProvider
Android号称提供了4大组件,分别是页面Activity、广播Broadcast、服务Service和内容提供器ContentProvider。其中内容提供器是跟数据存取有关的组件,完整的内容组件由内容提供器ContentProvider、内容解析器ContentResolver、内容观察器ContentObserver这三部分组成。
ContentProvider为App存取内部数据提供统一的外部接口,让不同的应用之间得以共享数据。像我们熟知的SQLite操作的是应用自身的内部数据库;文件的上传和下载操作的是后端服务器的文件;而ContentProvider操作的是本设备其他应用的内部数据,是一种中间层次的数据存储形式。
在实际编码中,ContentProvider只是一个服务端的数据存取接口,开发者需要在其基础上实现一个具体类,并重写以下相关数据库管理方法。
- onCreate:创建数据库并获得数据库连接。
- query:查询数据。
- insert:插入数据。
- update:更新数据。
- delete:删除数据。
- getType:获取数据类型。
这些方法看起来是不是很像SQLite?没错,ContentProvider作为中间接口,本身并不直接保存数据,而是通过SQLiteOpenHelper与SQLiteDatabase间接操作底层的SQLite。所以要想使用ContentProvider,首先得实现SQLite的数据表帮助类,然后由ContentProvider封装对外的接口。
既然内容提供器是四大组件之一,就得在AndroidManifest.xml中注册它的定义,并开放外部访问权限,注册代码如下:
注册完毕后就完成了服务端App的封装工作,接下来可由其他App进行数据存取。
内容解析器ContentResolver
前面提到了利用ContentProvider实现服务端App的数据封装,如果客户端App想访问对方的内部数据,就要通过内容解析器ContentResolver访问。内容解析器是客户端App操作服务端数据的工具,相对应的内容提供器是服务端的数据接口。要获取ContentResolver对象,在Activity代码中调用getContentResolver方法即可。
ContentResolver提供的方法与ContentProvider是一一对应的,比如query、insert、update、delete、getType等方法,连方法的参数类型都一模一样。其中,最常用的是query函数,调用该函数返回一个游标Cursor对象,这个游标与SQLite的游标是一样的。
下面是query方法的具体参数说明(依顺序排列)。
- uri:Uri类型,可以理解为本次操作的数据表路径。
- projection:字符串数组类型,指定将要查询的字段名称列表。
- selection:字符串类型,指定查询条件。
- selectionArgs:字符串数组类型,指定查询条件中的参数取值列表。
- sortOrder:字符串类型,指定排序条件。
内容观察器ContentObserver
ContentResolver获取数据采用的是主动查询方式,有查询就有数据,没查询就没数据。有时我们不但要获取以往的数据,还要实时获取新增的数据,最常见的业务场景是短信验证码。电商App经常在用户注册或付款时发送验证码短信,为了给用户省事,App通常会监控手机刚收到的验证码数字,并自动填入验证码输入框。这时就用到了内容观察器ContentObserver,给目标内容注册一个观察器,目标内容的数据一旦发生变化,观察器规定好的动作马上触发,从而执行开发者预先定义的代码。
总结一下在Content组件经常使用的系统URI,详细的URI取值说明见表4-3。
表4-3 常用的系统URI取值说明
相关文章:

【Android】数据存储
本章介绍Android五种主要存储方式的用法,包括共享参数SharedPreferences、数据库SQLite、SD卡文件、App的全局内存,另外介绍重要组件之一的应用Application的基本概念与常见用法,以及四大组件之一的内容提供器ContentProvider的基本概念与常见…...

个人网络安全的几个重点与防御
1 浏览器 firefox 这是第一选择 如果你真的不明白可以找找各个浏览器漏洞 mail 的危险的 来自与代理和漏洞 浏览器溢出漏洞 实时注意更新就可以 2 防火墙 大家都用windows 只需在 gpedit.msc 设置 但有什么未知漏洞就不得而知了 因为美国的计划问题 网络端口溢出漏洞 但…...

python爬虫 - 初识爬虫
🌈个人主页:https://blog.csdn.net/2401_86688088?typeblog 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、爬虫的关键概念 (一)HTTP请求与响应 ࿰…...

tomcat版本升级导致的umask问题
文章目录 1、问题背景2、问题分析3、深入研究4、umask4.1、umask的工作原理4.2、umask的计算方式4.3、示例4.4、如何设置umask4.5、注意事项 1、问题背景 我们的java服务是打成war包放在tomcat容器里运行的,有一天我像往常一样去查看服务的日志文件,却提…...

Golang | Leetcode Golang题解之第455题分发饼干
题目: 题解: func findContentChildren(g []int, s []int) (ans int) {sort.Ints(g)sort.Ints(s)m, n : len(g), len(s)for i, j : 0, 0; i < m && j < n; i {for j < n && g[i] > s[j] {j}if j < n {ansj}}return }...

vscode+stfp插件,实现远程自动同步文件代码
概述 远程同步代码,将本地代码实时保存到同一局域网内的另一台电脑(linux系统),这里的本地代码也可以是远程服务上的代码,即从一个远程ip同步到另一台远程ip服务器。 工具 vscode,SFTP插件 安装 vscod…...

python 实现djb2哈希算法
djb2哈希算法介绍 DJB2哈希算法是一种简单且快速的哈希算法,由Daniel J. Bernstein设计。这种算法的实现非常简单,适用于短键值的哈希表,也常被用于嵌入式设备和资源受限的系统。 基本原理 DJB2算法的原理是将输入的字符串视为一个字节数组…...

文件夹作为普通文件而非子模块管理
relaxed_ik_ros2 文件夹下存在 .gitmodules 文件和 .gitignore 文件。这说明该目录已经被 Git 识别为子模块。 要将这个文件夹作为普通文件而非子模块管理,你可以按以下步骤操作: 1. 删除子模块配置 首先删除 .gitmodules 文件中的子模块配置。你可以…...

7c结构体
文章目录 一、结构体的设计二、结构体变量的初始化2.1结构体在内存表示;**2.2**结构体类型声明和 结构体变量的定义和初始化只声明结构体类型声明类型的同时定义变量p1用已有结构体类型定义结构体变量p2*定义变量的同时赋初值。*匿名声明结构体类型 2.3 结构体嵌套及…...

浅聊前后端分离开发和前后端不分离开发模式
1.先聊聊Web开发的开发框架Spring MVC 首先要知道,Spring MVC是Web开发领域的一个知名框架,可以开发基于请求-响应模式的Web应用。而Web开发的本质是遵循HTTP(Hyper Text Transfer Protocol: 超文本传输协议)协议【发请求…...

RabbitMQ篇(死信交换机)
目录 一、简介 二、TTL过期时间 三、应用场景 一、简介 当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter) 消费者使用basic.reject或者basic.nack声明消费失败,并且消息的requeue参数设置为false消息是一个过…...

HBase 的 MemStore 详解
一、MemStore 概述 MemStore 是 HBase 的内存存储区域,它是一个负责缓存数据写入操作的组件。每当有写操作(如 Put 或 Delete)发生时,数据会首先被写入到 MemStore 中,而不是直接写入磁盘。MemStore 类似于数据库中的缓…...

【嵌入式软件-数据结构与算法】01-数据结构
摘录于老师的教学课程~~(*๓╰╯๓)~~内含链表、队列、栈、循环队列等详细介绍~~ 基础知识系列 有空再继续更~~~ 目录 【链表】 一、单链表 1、存储结构:带头结点的单链表 2、单链表结点类型的定义 3、创建单链表 1)头插法 2)尾插法 …...

Windows应用开发-解析AVI视频文件
本Windows应用解析AVI视频文件,以表格的方式显示AVI文件结构。并可以将结果保存到bmp图片。下面是,使用该应用解析一部AVI电影获得的图片。 应用开发信息 定义一个INFO结构,包含两个字符串对象,一个ULONGLONG变量,和…...

探索TCP协议的奥秘:Python中的网络通信
引言 在网络通信的世界里,TCP协议(传输控制协议)就如同一座桥梁,连接着数据的发送方和接收方。作为一名拥有20年实战经验的编码专家,我深知TCP协议在构建稳定、可靠的网络应用中的重要性。今天,我将带领大…...

每日学习一个数据结构-树
文章目录 树的相关概念一、树的定义二、树的基本术语三、树的分类四、特殊类型的树五、树的遍历六、树的应用场景 树的遍历一、前序遍历二、中序遍历三、后序遍历使用java代码实现遍历总结 树的相关概念 树是一种重要的非线性数据结构,在计算机科学中有着广泛的应用…...

简单PCL库读文件(linux vscode编译)
#include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/common/common.h> #include <iostream>int main(int argc, char** argv) {if (argc ! 2) {std::cerr << "请指定 PCD 文件路径" << std::endl;return -…...

【自动驾驶】最近计划看的论文
将对应的论文链接贴出来,当作监督自己。 方向:端到端自动驾驶 方法论文代码UniADhttps://arxiv.org/pdf/2212.10156https://github.com/OpenDriveLab/UniADVADhttps://arxiv.org/pdf/2303.12077https://github.com/hustvl/VADUADhttps://arxiv.org/pdf…...

vue3学习:axios输入城市名称查询该城市天气
说来惭愧,接触前端也有很长一段时间了,最近才学习axios与后端的交互。今天学习了一个查询城市天气的案例,只需输入城市名称,点击“查询”按钮便可以进行查询。运行效果如下: 案例只实现了基本的查询功能,没…...

影刀RPA实战:Excel拆分与合并工作表
1.影刀操作excel的优势 Excel,大家都不陌生,它是微软公司推出的一款电子表格软件,它是 Microsoft Office 套件的一部分。Excel 以其强大的数据处理、分析和可视化功能而闻名,广泛应用于商业、教育、科研等领域。可以说࿰…...

STM32三种启动模式:【详细讲解】
STM32在上电后,从那里启动是由BOOT0和BOOT1引脚的电平决定的,如下表: BOOT模式选引脚启动模式BOOT0BOOT1X0主Flash启动01系统存储器启动11内置SRAM启动 BOOT 引脚的值在重置后 SYSCLK 的第四个上升沿时被锁定。在重置后,由用户决定是如何设…...

Ray_Tracing_The_Next_Week
1动态模糊 动态模糊在摄影中就是快门的速度慢,捕捉光的时间长,物体运动时进行捕捉成像,拍出来的结果是这个运动过程每一帧的平均值 我们的思路是: 每一条光线都拥有自己存在的一个时间点。随着时间变化随机生成光线,一般来说我…...

DBT hook 实战教程
本文将介绍dbt中在模型和seed级别使用post-hook的几个具体示例。dbt中的Post-hooks是一个强大而简单的特性,它在构建模型之后(如果是pre-hook,甚至在此之前)执行SQL语句。这些语句实际上(几乎)可以是任何东西,从将表复制到另一个数据库/模式&…...

SpringBoot整合JPA详解
SpringBoot版本是2.0以上(2.6.13) JDK是1.8 一、依赖 <dependencies><!-- jdbc --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency><!--…...

【微服务】springboot 实现动态修改接口返回值
目录 一、前言 二、动态修改接口返回结果实现方案总结 2.1 使用反射动态修改返回结果参数 2.1.1 认识反射 2.1.2 反射的作用 2.1.3 反射相关的类 2.1.4 反射实现接口参数动态修改实现思路 2.2 使用ControllerAdvice 注解动态修改返回结果参数 2.2.1 注解…...

【前端开发入门】html快速入门
目录 引言一、html基础模板内容二、html文档流三、html 标签1.块级元素2.行内元素3.功能性元素4.标签嵌套 四、html编码习惯五、总结 引言 本系列教程旨在帮助一些零基础的玩家快速上手前端开发。基于我自学的经验会删减部分使用频率不高的内容,并不代表这部分内容不…...

python配置环境变量
方法一:首先卸载重新安装,在安装时勾选增加环境变量 方法二:我的电脑-属性-高级系统配置 手动添加环境变量,路径为python的安装路径 检查:查看环境变量是否安装成功 安装第三方lib winr,输入cmd pip ins…...

从0到1:培训机构排课小程序开发笔记一
业务调研 随着人们生活水平的提高,健康意识和学习需求日益增强,私教、健身和培训机构的市场需求迅速增长。高效的排课系统不仅可以提升机构的管理效率,还能提高学员的满意度。解决传统的排课方式存在的时间冲突、信息不对称、人工操作繁琐等…...

方法重载(Overload)
前言 在前面的学习中,我们学到了重写(Override),这里我们主要进行重载(Overload)的介绍,同时对重写和重载的区别进行分析。 1. 重载(Overload) #方法重载 在同一个类中定义多个同名但参数不同的方法。我们称方法与方法之间构成方法重载 在Java中&…...

[论文笔记]SGPT: GPT Sentence Embeddings for Semantic Search
引言 解码器Transformer的规模不断壮大,轻松达到千亿级参数。同时由于该规模,基于提示或微调在各种NLP任务上达到SOTA结果。但目前为止解码器Transformer还无法应用在语义搜索或语句嵌入上。 为了简单,下文中以翻译的口吻记录,比…...