Supabase Kotlin客户端的基本使用
kotlin
介绍
Supabase | The Open Source Firebase Alternative号称是Firebase的替代方案,这个项目在Github已经获得了将近60K的Star。目前它可用的服务有:
- Database:使用Postgres作为数据库支持
- Authentication:每个Suabase项目都配有一个完整的用户管理系统,无需任何其他工具即可工作
- Storage:一个开源对象存储,具有无限的可扩展性,适用于任何文件类型
- Edge Functions:以快速部署时间和低延迟执行最接近用户的代码
- Realtime:实时通过WebSockets全局同步客户端状态,多人协作
- Vector:用于开发人工智能应用程序的开源矢量数据库
这些服务基本可以用于我目前开发的简单的项目,而且它也不只支持一种客户端。其中有些客户端是由社区维护的,Kotlin就是其中之一
本文只涉及前三个服务
Supabase Kotlin Client - Introduction这个是客户端的使用文档,对于刚学Koltin不久的我来说实在有点晦涩难懂,不过对于理解了基本用法之后就相对流畅一点了
注册账号和创建项目的流程我这里就略过了,不细说了
初始化客户端
要使用他的客户端,需要先获取已经注册好的账户的项目URL和公钥,在下图位置可以找到
然后需要在(:app)build.gradle.kts
中引入如下三种依赖:
- BOM版本管理
- HTTP请求引擎
- JSON序列化
目前的最新版是1.4.7
,代码如下:
// 指定版本
implementation("io.github.jan-tennert.supabase:bom:1.4.7")
// http客户端 okhttp
runtimeOnly("io.ktor:ktor-client-okhttp:2.3.5")
// jackson 序列化
implementation("io.github.jan-tennert.supabase:serializer-jackson-android:1.4.7")
等待依赖构建完毕,就可以编写实例化客户端的代码了:
val client = createSupabaseClient(
// 项目URL
supabaseUrl = "https://xxx.supabase.co",
supabaseKey = "anon",
) {
// 用于配置客户端,比如加载Database的依赖之类的
}
我一般都是把这个客户端放在单例里面的,方便使用
Database
首先是数据库的使用,先创建数据表。需要注意的是开启了RLS后(这边先关掉),需要在Authentication配置数据表的Policies,这个有些复杂也有些偏题了,如果有需要的话我可以研究一下再出一篇聊一下
如果在创建字段时没找到到需要的数据类型需要在PgAdmin中手动创建一列并选择数据类型
创建好数据表之后我们可就可以开始使用了,引入依赖:
implementation("io.github.jan-tennert.supabase:postgrest-kt")
然后修改客户端配置
val client = createSupabaseClient(
supabaseUrl = "https://xxx.supabase.co",
supabaseKey = "<anon key>"
) {
// 配置序列化器
defaultSerializer = JacksonSerializer()
// 安装Database插件
install(Postgrest)
}
接下来的步骤:
- 编写实体类
- 编写获取数据的代码
// 实体类
data class Demo(val id: Int, val name: String)
// 获取数据的代码
val res = client.postgrest["Demo"].select().decodeList<Demo>()
for (item in res) {
Log.d("DemoDB", "name: ${item.name}, id: ${item.id}")
}
Authentication
然后就是用户管理的接口使用,这边就简单梳理一下使用邮箱登陆和注册的流程。
- 引入依赖
implementation("io.github.jan-tennert.supabase:gotrue-kt")
- 修改客户端配置
install(GoTrue)
- 简单注册
// 注册
val user = supabaseClient.gotrue.signUpWith(Email) {
email = "example@email.com"
password = "example-password"
}
注意注册完毕需要在Web管理界面通过用户注册的请求
上面是简单的注册API的使用方式,然后是登陆。我当时看的时候一开始死活获取不到登陆后的回调,没想到他是使用了Kotlin的Flow
,当时没理解就浪费了很多的时间
下面我会编写一个封装后的api,思路如下:
- 使用单例存储登陆状态
- 实例化后开启Flow监听登陆状态的变化
- 通过Flow回调响应登陆结果
SupabaseApi是我的另一个单例
class AccessApi {
companion object {
// user login status
var loginStatus: SessionStatus = SessionStatus.NotAuthenticated
var currentUser: UserInfo? = null
var loginType: String = "NotAuthenticated"
}
init {
GlobalScope.launch {
// Flow
SupabaseApi.supabaseClient.gotrue.sessionStatus.collect {
loginStatus = it
when (it) {
is SessionStatus.NotAuthenticated -> Log.d("Access Api", "NotAuthenticated")
is SessionStatus.Authenticated -> {
currentUser = it.session.user
loginType = it.session.type
Log.d("Access Api", "Authenticated")
}
is SessionStatus.NetworkError -> Log.d("Access Api", "NetworkError")
is SessionStatus.LoadingFromStorage -> Log.d("Access Api", "LoadingFromStorage")
else -> Log.d("Access Api", "Unknown")
}
}
}
}
suspend fun loginWithEmailAndPassword(inputEmail: String, inputPassword: String) {
try {
SupabaseApi.supabaseClient.gotrue.loginWith(Email) {
email = inputEmail
password = inputPassword
}
} catch (e: Exception) {
Log.d(
"Access Api",
"loginWithEmailAndPassword(inputEmail: String, inputPassword: String) Login field, msg: ${e.message}"
)
}
}
suspend fun logout() {
SupabaseApi.supabaseClient.gotrue.logout(LogoutScope.GLOBAL)
}
}
主要使用的api如下:
- gotrue.logout(LogoutScope):登出
- gotrue.loginWith(Email):邮件登陆
- gotrue.sessionStatus.collect:通过Kotlin协程的Flow获取登陆状态变更事件
我们可以通过currentUser
获取当前用户信息,loginStatus
获取登陆状态
Storage
最后是Storage,可以简单理解为一个图床之类的服务。
- 引入依赖
implementation("io.github.jan-tennert.supabase:storage-kt")
- 修改客户端配置
install(Storage)
- 客户端使用
// 查询music库中的文件
val bucket = supabaseClient.storage["music"]
val files = bucket.list()
for (file in files) {
println("name: ${file.name}, id: ${file.id}")
}
// 获取指定bucketName的指定文件
val bucket = SupabaseApi.supabaseClient.storage[bucketName]
val bytes = bucket.downloadAuthenticated(fileFullPath)
总结
其实我在一开始使用的时候就感觉auth的使用方法有点反直觉的(主要之前前端异步登陆写多了,不习惯),现在理解了之后其实感觉这样写也不错
上面三种服务的基本使用方式我差不多就整理到这里。欢迎大佬多多交流
参考文档:
分享这篇文章