Протягом останніх двох років Room був переважним рішенням для роботи з SQLite в Android. Але нещодавно була випущена нова версія бібліотеки SQLDelight, яка підтримує kotlin multiplatform, має перероблений api, новий генерований Kotlin-код, розширення до RxJava2, підтримує Paging-бібліотеки та багато іншого. З його можливістю генерувати в live-режимі typesafe kotlin код з чистого SQL за допомогою плагіну Android Studio важко конкурувати. Чи все ще варто розглядати інші рішення, маючи такий потужний інструмент?!
На цій сесії ми розглянемо основні можливості SQLDelight та в live-режимі побачимо, як він працює. Розберемо типові випадки його використання та поміркуємо про можливості multiplatform використання SQLDelight у майбутньому.
http://uamobile.org/uk/topics/leave-your-room-behind
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Leave your Room behind - UA Mobile 2019
1. Leave your Room behind
Rakhimov Andrii
Lead Android Engineer at Lalafo
andrii.rakhimov@gmail.com
2. Agenda
● Our own story towards SQLite
● What is a good android SQLite abstraction?
● Schema generation
● Statements
● Migrations
● RxJava, Paging libraries
● Future
7. Shared Preferences
+ Simple
+ Works with 100 of values
- Slow, file will be rewritten each time
- Slow, manual querying of data
- Data duplication
- Threading
- Scales badly
17. Schema generation and types
CREATE TABLE some_types (
some_long INTEGER NOT NULL PRIMARY KEY, -- Stored as INTEGER in db, retrieved
as Long
some_double REAL, -- Stored as REAL in db, retrieved as Double
some_string TEXT, -- Stored as TEXT in db, retrieved as String
some_blob BLOB, -- Stored as BLOB in db, retrieved as ByteArray
some_int INTEGER AS Int, -- Stored as INTEGER in db, retrieved as Int
some_short INTEGER AS Short, -- Stored as INTEGER in db, retrieved as Short
some_float REAL AS Float -- Stored as REAL in db, retrieved as Float
);
18. Custom Column Types
import ...Message;
CREATE TABLE messages(
_id TEXT NOT NULL PRIMARY KEY,
message BLOB AS Message
);
class SerializeAdapter<T : Any> : ColumnAdapter<T, ByteArray> {
override fun decode(bytes: ByteArray) = SerializeUtils.deserialize(bytes) as T
override fun encode(t: T): ByteArray = SerializeUtils.serialize(t)
}
val db = LalafoDb.invoke(
AndroidSqliteDriver(helper),
Messages.Adapter(SerializeAdapter<Message>())
)
19. Enums
Import ....SendStatus;
CREATE TABLE messages(
_id TEXT NOT NULL PRIMARY KEY,
status TEXT AS SendStatus
);
val db = LalafoDb.invoke(
AndroidSqliteDriver(helper),
Messages.Adapter(EnumColumnAdapter())
)
20. SQLite statements
getMessages:
SELECT * FROM messages
WHERE chat_id = ?
ORDER BY creation_time
DESC LIMIT 60
val messages = lalafoDb.messagesQueries.getMessages(chatId)
val list: List<Messages> = messages.executeAsList()
22. Driver in real app
@Provides @Singleton static SupportSQLiteOpenHelper provideSQLiteOpenHelper(App context) {
SupportSQLiteOpenHelper.Configuration configuration =
SupportSQLiteOpenHelper.Configuration.builder(context)
.name(DbCallback.DB_NAME)
.callback(new DbCallback(context))
.build();
SupportSQLiteOpenHelper.Factory factory = new FrameworkSQLiteOpenHelperFactory();
return factory.create(configuration);
}
@Provides @Singleton static LalafoDb provideDb(SupportSQLiteOpenHelper helper) {
return LalafoDb.Companion.invoke(
new AndroidSqliteDriver(helper),
new Categories.Adapter(new SerializeAdapter<>()),
...
new Messages.Adapter(new EnumColumnAdapter<>(SendStatus.values())
)...
23. Migrations
DROP TABLE IF EXISTS chats;
DROP TABLE IF EXISTS messages;
CREATE TABLE chats(
thread_id TEXT NOT NULL PRIMARY KEY,
updated INTEGER NOT NULL,
...
);
CREATE TABLE messages(
_id TEXT NOT NULL PRIMARY KEY,
creation_time INTEGER NOT NULL,
...
);
25. RxJava
getMessages:
SELECT * FROM messages
WHERE chat_id = ?
ORDER BY creation_time
DESC LIMIT 60
val messagesStream = lalafoDb.messagesQueries
.getMessages(chatId)
.asObservable(Schedulers.io())
.mapToList()
26. Android Paging
countMessages:
SELECT count(*) FROM messages;
getMessages:
SELECT *
FROM messages
LIMIT :limit OFFSET :offset;
val messagesQueries = lalafoDb.messagesQueries
val dataSource = QueryDataSourceFactory(
queryProvider = messagesQueries::getMessage,
countQuery = messagesQueries.countMessages()
).create()