当前位置: 首页 > news >正文

政府门户网站建设多元化国内seo公司哪家最好

政府门户网站建设多元化,国内seo公司哪家最好,福州做网站的公司多少钱,网购平台哪个好简述 Android Jetpack的出现统一了Android开发生态,各种三方库逐渐被官方组件所取代。Room也同样如此,逐渐取代竞品成为最主流的数据库ORM框架。这当然不仅仅因为其官方身份,更是因为其良好的开发体验,大大降低了SQLite的使用门槛…

简述

Android Jetpack的出现统一了Android开发生态,各种三方库逐渐被官方组件所取代。Room也同样如此,逐渐取代竞品成为最主流的数据库ORM框架。这当然不仅仅因为其官方身份,更是因为其良好的开发体验,大大降低了SQLite的使用门槛。

Room是Google官方在SQLite基础上封装的一款数据持久库,是Jetpack全家桶的一员,和Jetpack其他库有着可以高度搭配协调的天然优势。Room使用APT技术,大大简化了使用SQLite的代码量,只需使用注解配合少量代码即可实现高效的数据库操作。

Room基本介绍

框架特点

相对于SQLiteOpenHelper等传统方法,使用Room操作SQLite有以下优势:

  • 编译期的SQL语法检查
  • 开发高效,避免大量模板代码
  • API设计友好,容易理解
  • 可以与RxJava、 LiveData 、 Kotlin Coroutines等进行桥接

添加依赖

dependencies {implementation "androidx.room:room-runtime:2.2.5"kapt "androidx.room:room-compiler:2.2.5"
}

基本组件

Room的使用,主要涉及以下3个组件

  • Database: 访问底层数据库的入口
  • Entity: 代表数据库中的表(table),一般用注解
  • Data Access Object (DAO): 数据库访问者

这三个组件的概念也出现在其他ORM框架中,有过使用经验的同学理解起来并不困难: 通过Database获取DAO,然后通过DAO查询并获取entities,最终通过entities对数据库table中数据进行读写

实例实战

​
insert:使用注解 @Insert,Room 会自动将所有参数在单个事物中插入数据库
@Insert
public fun inertUser (user: User)  // 单个参数可以返回 long
​
@Insert
public fun insertUserList (array: Array<User>)  // 参数为集合可以返回 long []
数据库添加 User
val user = User()
user.name = "赵云 编号 = $number"
val address = Address()
address.street = "成都接头"
address.state = "蜀汉"
address.city = "常山"
address.postCode = 10010
user.address = address
userDao.inertUser (user)  // 添加 User
添加数据结果:
​
​
upadte:使用 @Update 注解
@Update
public fun update (user: User)   // 可以让此方法返回一个 int 值,表示数据库中更新的行数  val user = User()
user.id = 1
user.name = "张翼德"
address.city = "涿郡"
.....
userDao.update(user)
点击 Update 后再查询结果:此时的赵云已经改为张翼徳了
​
​
delete:使用 @Delete 注解
@Delete 
public fun delete (user: User)   // 可以返回一个 int 值,表示从数据库中删除的行数val user = User()
user.id = 1    // 要删除的主键 id
userDao.delete(user)
点击 delete 后再次查询数据:编号为 1 的数据已被删除
​
​
查询信息 :@Query 注解对数据库执行读 / 写操作
@Query("SELECT * FROM user")
public fun selectAll (): Array<User>   // 查询所有数据@Query("SELECT * FROM user WHERE name = :name")
public fun selectUser (name:String): Array<User>   // 条件查询
返回列的子集:创建子类在每个属性中使用 @ColumnInfo (name = "name") 标记对应数据库中的列名
public class UserTuple {                  // 1、根据要查询的字段创建 POJO 对象      @ColumnInfo(name = "name")public var name: String? = null@ColumnInfo(name = "city")public var city: String? = null
}@Query ("SELECT name ,city FROM user")  // 2、查询的结果会映射到创建的对象中public List<UserTuple> loadFullName();val userList = userDao.loadFullName()
for (userTuple in userList) {stringBuilder.append(userTuple.name).append("  ").append(userTuple.city).append("\n")
}
输出的结果:只有 name 和 city 两列
​
​
范围条件查询 :查询城市中所有用户
@Query("SELECT name ,street FROM user WHERE city IN (:cityArray)")
fun loadUserInCity(cityArray: Array<String>): List<UserTuple>val userList = userDao.loadUserInCity (arrayOf ("常山"))  // 查询常山,只会出现赵云不会出现张翼德
​
​
Observable 查询:使用 LiveData 作为查询方法的返回值,注册观察者后,数据表更改时自动更新 UI
@Query("SELECT name ,street FROM user WHERE city IN (:cityArray"))
fun loadUserInCityLive(cityArray: Array<String>): LiveData<List<UserTuple>>
​
​
​
private lateinit var liveData: LiveData<Array<UserTuple>>  // 定义一个 LiveData
get() {
return userDao.loadUserInCityLive (arrayOf ("常山"))
}
​
val observer = Observer<Array<UserTuple>> {    // 定义一个观察者val stringBuilder = StringBuilder()for (index in it!!.indices) {val userTuple = it[index]stringBuilder.append(userTuple.name).append("  ").append(userTuple.name).append("  \n")}tv_main_show.text = stringBuilder.toString()
}
liveData.observe (this, observer)   // 注册观察者
运行结果:此时当添加数据时,UI 会自动更新;
​
RxJava 查询 :返回 Observable 实例可以使用 RxJava 订阅观察者
@Query("SELECT * FROM user WHERE id = :id LIMIT 1")
fun loadUserRxJava(id:Int) : Flowable<User>
​
​
userDao.loadUserRxJava(4).subscribe(Consumer {val stringBuilder = StringBuilder()stringBuilder.append(it.id).append("  ").append(it.name).append("  \n")tv_main_show.text = stringBuilder.toString()})
​
​Cursor 查询:返回 Cursor 对象
fun loadUserCursor(id:Int) : Cursor
多表查询:根据表的外键多表查询
@Query("SELECT user.name AS userName, pet.name AS petName "+ "FROM user, pet "+ "WHERE user.id = pet.user_id")

源码分析

从上面的Demo代码可以看出,Room有很多的注解,实际上Room正是通过APT注解处理器,自动生成了许多代码,避免使用者在为了使用数据库编写重复的模板代码。

1.Room.databaseBuilder.build()

数据库使用的入口,也就是构造RoomDatabase的实例,它里面会根据buider中做的配置,进行一系列赋值操作,生成一个 DatabaseConfiguration对象,然后传入的 class 对象,调用Class.newInstance()方法,获取到RoomDatabase的实例。 接着就是调用RoomDatabase.init进行初始化操作。

public T build() {//...省略DatabaseConfiguration configuration =new DatabaseConfiguration(mContext,mName,factory,mMigrationContainer,mCallbacks,mAllowMainThreadQueries,mJournalMode.resolve(mContext),mQueryExecutor,mTransactionExecutor,mMultiInstanceInvalidation,mRequireMigration,mAllowDestructiveMigrationOnDowngrade,mMigrationsNotRequiredFrom,mCopyFromAssetPath,mCopyFromFile,mCopyFromInputStream,mPrepackagedDatabaseCallback,mTypeConverters);T db = Room.getGeneratedImplementation(mDatabaseClass, DB_IMPL_SUFFIX);db.init(configuration);return db;
}

2.RoomDatabase.init()

调用了createOpenHelper方法,createOpenHelper方法实现在AppDatabase_Impl中,创建了RoomOpenHelper,RoomOpenHelper继承SupportSQLiteOpenHelper.Callback。 引申:注意这里的 AutoCloser对象,这里没有仔细研究它的代码,但是它应该是代理持有了一个 SupportSQLiteOpenHelper对象,可以实现在提交数据库事务之后,自动的判断并close数据库。 从这里就可以看出,Room实际上是对 SQLite的再次封装,但是通过 APT 以及其他辅助类,使得Room的比直接用SQLite要简便很多。

@Overrideprotected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration,new RoomOpenHelper.Delegate(2) {//...省略}
}
​
@CallSuper
public void init(@NonNull DatabaseConfiguration configuration) {mOpenHelper = createOpenHelper(configuration);
​// Configure SqliteCopyOpenHelper if it is available:SQLiteCopyOpenHelper copyOpenHelper = unwrapOpenHelper(SQLiteCopyOpenHelper.class,mOpenHelper);if (copyOpenHelper != null) {copyOpenHelper.setDatabaseConfiguration(configuration);}
​AutoClosingRoomOpenHelper autoClosingRoomOpenHelper =unwrapOpenHelper(AutoClosingRoomOpenHelper.class, mOpenHelper);
​if (autoClosingRoomOpenHelper != null) {mAutoCloser = autoClosingRoomOpenHelper.getAutoCloser();mInvalidationTracker.setAutoCloser(mAutoCloser);}  // ... 省略
}            

3.AppDatabase.getUserDao()

AppDatabase是我们继承自RoomDatabase的抽象类,我们在里面添加了获取UserDao的方法,Room 会通过APT技术,在编译之后自动帮我们添加对应的实现。

@Overridepublic UserDao getUerDao() {if (_userDao != null) {return _userDao;} else {synchronized(this) {if(_userDao == null) {_userDao = new UserDao_Impl(this);}return _userDao;}}}

4.UserDao_Impl

可以看出来,UserDao_Impl根据注解,具体的实现了我们在 UserDao接口中添加的方法,其中的关键点就在于,根据我们添加在注解中的 sql 语句,生成了对数据库的访问代码。

@Override
public void insertUserRecord(final User user) {__db.assertNotSuspendingTransaction();__db.beginTransaction();try {__insertionAdapterOfUser.insert(user);__db.setTransactionSuccessful();} finally {__db.endTransaction();}
}
​
@Override
public User geUerById(final String id) {final String _sql = "select *from User where id = (?)";final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);int _argIndex = 1;if (id == null) {_statement.bindNull(_argIndex);} else {_statement.bindString(_argIndex, id);}__db.assertNotSuspendingTransaction();final Cursor _cursor = DBUtil.query(__db, _statement, false, null);try {final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");final User _result;if(_cursor.moveToFirst()) {final String _tmpId;if (_cursor.isNull(_cursorIndexOfId)) {_tmpId = null;} else {_tmpId = _cursor.getString(_cursorIndexOfId);}final String _tmpName;if (_cursor.isNull(_cursorIndexOfName)) {_tmpName = null;} else {_tmpName = _cursor.getString(_cursorIndexOfName);}_result = new User(_tmpId,_tmpName);} else {_result = null;}return _result;} finally {_cursor.close();_statement.release();}
}

总结

本文只是对Room的一个简单分析,正如在一开始的概述里面说的那样:Room是对SQLite数据库的抽象,它提供了很多便利的API和注解等,简化了使用者使用数据库的方式。本文没有分析 Room和 LiveData结合使用的情况,因为笔者公司的项目还没能引入 LiveData。

抛开这一点不谈,个人认为它有两个比较显著的优点: 1、当然就是通过APT技术,TypeConverter 等,简化了使用,减少了大量的访问数据库的模板代码。 2、是文中也有提到的,它对数据库升级的优化,除了可以避免两个分支同时升级数据库但是合并不冲突导致的错误之外,它还提供了对数据库升级做单元测试的工具类,安全性提升很多。

http://www.tj-hxxt.cn/news/38042.html

相关文章:

  • 国外设计网站导航seo模拟点击软件源码
  • 同个网站可以做多个外链吗2023年5月份病毒感染情况
  • 专业做曝光引流网站福州网站建设
  • 网站建设中的咨询服务著名的网络营销案例
  • 湘潭做网站 去磐石网络百度seo优化多少钱
  • go 做视频网站重庆官网seo分析
  • 做网站买主机还是服务器谈谈你对seo概念的理解
  • 楚雄网站开发万网域名注册查询
  • 民治做网站推广赚钱的app
  • 公司网站建设的重要性seo一个月工资一般多少
  • html做分模块的网站seo站长工具下载
  • 宁波小网站制作推广快速排名seo
  • 深圳建设网站哪里好百度搜题
  • 地产项目网站免费模板素材网站
  • 教育网站官网入口seo高端培训
  • 怎么自己做blog网站杭州百度首页优化
  • 免费做网站推荐哔哩哔哩b站在线看免费
  • 网站建设 推神网络谷歌推广费用
  • 什么网站可以做直播seo收费低
  • jsp网站开发需要哪些技术武汉网站推广公司排名
  • 渭南做网站都有哪些网络营销课程设计
  • 做网站推广的工资中国网新山东
  • 网站制作开发的步骤和方法太原seo哪家好
  • 成都网站建设-中国互联自媒体营销代理
  • 小程序开发成都公司seo外链平台
  • 公司做网站,要准备哪些素材chrome官网下载
  • 防做网站视频西安seo优化系统
  • 南通高端网站建设机构什么软件可以优化关键词
  • 阜阳html5网站建设一站式快速网站排名多少钱
  • 南宁网站建设gxjzdrj网络营销推广方式包括哪几种