Google Architecture Components 使用
程序员文章站
2022-06-16 16:48:16
...
architecture components使用google新推出的Android 架构组件,目标是帮助我们设计更好、可测试和可维护应用程序。它可以自动管理UI组件生命周期,也能处理数据持久化的问题。
环境
- 编译器:Android Studio3.0
- 开发语言:kotlin
接入
接入方式还算比较简单
在Project的build.gradle添加
buildscript {
ext.ac_version='1.0.0'
repositories {
google()
}
}
在app的build.gradle添加
apply plugin: 'kotlin-kapt'
dependencies {
/// Architecture Components
implementation "android.arch.lifecycle:runtime:$ac_version"
implementation "android.arch.lifecycle:extensions:$ac_version"
kapt "android.arch.lifecycle:compiler:$ac_version"
/// Room
implementation "android.arch.persistence.room:runtime:$ac_version"
kapt "android.arch.persistence.room:compiler:$ac_version"
}
这样写完后依赖库就添加完成了。
使用
首先我们创建一个MainActivity
布局文件我们可以这样写
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.bobbygu.googlearchitecture.MainActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Google Architecture框架\n数据持久化"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.01" />
<Button
android:id="@+id/btn_insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="模拟插入"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
<Button
android:id="@+id/btn_delete_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除所有"
app:layout_constraintStart_toEndOf="@+id/btn_insert"
app:layout_constraintTop_toTopOf="@+id/btn_insert" />
<Button
android:id="@+id/btn_get_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取数据"
app:layout_constraintStart_toEndOf="@+id/btn_delete_all"
app:layout_constraintTop_toTopOf="@+id/btn_insert" />
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:maxLines="10"
android:minLines="1"
android:scrollbars="vertical"
android:text="数据库数据显示"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_insert_one" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="数据库操作:"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv1" />
<Button
android:id="@+id/btn_insert_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="插入一个"
app:layout_constraintEnd_toStartOf="@+id/btn_delete_all"
app:layout_constraintStart_toStartOf="@+id/btn_insert"
app:layout_constraintTop_toBottomOf="@+id/btn_insert" />
<Button
android:id="@+id/btn_delete_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除一个"
app:layout_constraintStart_toEndOf="@+id/btn_insert_one"
app:layout_constraintTop_toTopOf="@+id/btn_insert_one" />
</android.support.constraint.ConstraintLayout>
ConstraintLayout使用不熟练的话可以看这个:ConstraintLayout 完全解析 快来优化你的布局吧
MainActivity.kt是这样的
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv2.movementMethod = ScrollingMovementMethod.getInstance()
DatabaseManager.initDb(this)
val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
model.users.observe(this, Observer { users ->
if (users != null && users.isNotEmpty()) {
tv1.text = users[0].name
}
})
model.stories.observe(this, Observer { stories ->
Log.d("Main", "stories:" + stories)
if (stories != null) {
var str = ""
for (story in stories) {
str += "title:" + story.title + "\n"
}
tv2.text = str
}
})
btn_insert.setOnClickListener {
DatabaseManager.simlutateInsertData()
}
btn_insert_one.setOnClickListener {
val story = Story()
story.data = "BobbyApp"
story.displayData = "BobbyApp displayData"
story.title = "BobbyApp" + System.currentTimeMillis()
DatabaseManager.insertStory(story)
}
btn_delete_all.setOnClickListener {
//访问数据库需要到子线程
Thread({
DatabaseManager.deleteAllStories()
}).start()
}
btn_delete_one.setOnClickListener {
DatabaseManager.deleteStory()
}
btn_get_data.setOnClickListener {
DatabaseManager.loadAllStories().observe(this, Observer { stories ->
model.stories.value = stories
})
}
}
}
ViewModel
源码:
public abstract class ViewModel {
/**
* This method will be called when this ViewModel is no longer used and will be destroyed.
* <p>
* It is useful when ViewModel observes some data and you need to clear this subscription to
* prevent a leak of this ViewModel.
*/
@SuppressWarnings("WeakerAccess")
protected void onCleared() {
}
}
主要负责View层与Model层中的逻辑交互
LiveData
- 定义
var users: MutableLiveData<List<User>> = MutableLiveData()
get() {
if (field.value == null) {
Handler().postDelayed({ loadUsers() }, 3000)
}
return field
}
- 使用
if (users != null && users.isNotEmpty()) {
tv1.text = users[0].name
}
})" data-snippet-id="ext.76ffb026824cc5218376323da8b4e239" data-snippet-saved="false" data-codota-status="done">val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
model.users.observe(this, Observer { users ->
if (users != null && users.isNotEmpty()) {
tv1.text = users[0].name
}
})
更新数据
users.value = list
Room
- Entity
@Entity(tableName = "stories")
class Story {
@PrimaryKey(autoGenerate = true)
var id = 0
var data = ""
var displayData = ""
var title = ""
override fun toString(): String {
return "Story(id=$id, data='$data', displayData='$displayData', title='$title')"
}
}
- Dao
@Dao
interface StoryDao {
@Query("select * from stories")
fun loadAllStories(): LiveData<List<Story>>
@Query("select * from stories")
fun getAllStories(): List<Story>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertStories(list: List<Story>)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertStories(vararg story: Story)
@Query("delete from stories")
fun deleteAllStories(): Int
@Delete
fun deleteStories(vararg story: Story): Int
@Update
fun updateStories(vararg story: Story): Int
}
- Database
@Database(entities = [(Story::class)], version = 1)
abstract class AppDatabase : RoomDatabase() {
companion object {
val TAG = "bobby_story_db"
}
abstract fun storyDao(): StoryDao
}
- 使用
) {
Thread({
db.beginTransaction()
try {
db.storyDao().insertStories(stories)
db.setTransactionSuccessful()
} finally {
db.endTransaction()
}
}).start()
}
fun insertStory(story: Story) {
Thread({
db.beginTransaction()
try {
db.storyDao().insertStories(story)
db.setTransactionSuccessful()
} finally {
db.endTransaction()
}
}).start()
}
fun deleteAllStories(): Int {
return db.storyDao().deleteAllStories()
}
fun deleteStory() {
Thread({
val stories = getAllStories()
Log.d("delete", stories.toString())
if (stories.isNotEmpty()) {
db.storyDao().deleteStories(stories[0])
}
}).start()
}
fun getAllStories(): List {
return db.storyDao().getAllStories()
}
fun loadAllStories(): LiveData> {
return db.storyDao().loadAllStories()
}
fun simlutateInsertData() {
val list = ArrayList()
for (i in 1..20) {
val s = Story()
s.id = (i)
s.data = "bobby-" + i.toString()
s.displayData = "bobby-" + i.toString()
s.title = "bobby-" + i.toString()
list.add(s)
}
insertStories(list)
}
}" data-snippet-id="ext.44eb1a6469e3010b1d1bb135b70e90ce" data-snippet-saved="false" data-codota-status="done">object DatabaseManager {
private lateinit var db: AppDatabase
fun initDb(context: Context) {
db = Room.databaseBuilder(context, AppDatabase::class.java, AppDatabase.TAG).build()
}
fun insertStories(stories: List<Story>) {
Thread({
db.beginTransaction()
try {
db.storyDao().insertStories(stories)
db.setTransactionSuccessful()
} finally {
db.endTransaction()
}
}).start()
}
fun insertStory(story: Story) {
Thread({
db.beginTransaction()
try {
db.storyDao().insertStories(story)
db.setTransactionSuccessful()
} finally {
db.endTransaction()
}
}).start()
}
fun deleteAllStories(): Int {
return db.storyDao().deleteAllStories()
}
fun deleteStory() {
Thread({
val stories = getAllStories()
Log.d("delete", stories.toString())
if (stories.isNotEmpty()) {
db.storyDao().deleteStories(stories[0])
}
}).start()
}
fun getAllStories(): List<Story> {
return db.storyDao().getAllStories()
}
fun loadAllStories(): LiveData<List<Story>> {
return db.storyDao().loadAllStories()
}
fun simlutateInsertData() {
val list = ArrayList<Story>()
for (i in 1..20) {
val s = Story()
s.id = (i)
s.data = "bobby-" + i.toString()
s.displayData = "bobby-" + i.toString()
s.title = "bobby-" + i.toString()
list.add(s)
}
insertStories(list)
}
}
最后来个效果展示:
推荐阅读
-
Google搜索应用在Win10正式版系统中怎么使用?
-
Google开源的Python格式化工具YAPF的安装和使用教程
-
网站上使用Google DFP广告管理系统来刊登广告的教程
-
网页使用Google Font API(字体)的方法
-
google trends(谷歌趋势)的使用方法和技巧
-
php使用google地图应用实例
-
python使用xmlrpclib模块实现对百度google的ping功能
-
Google和Facebook不使用Docker的原理解析
-
使用KubeAdm部署Kubernetes集群——如何访问google代码仓库及Yum源
-
使用Google Cloud SDK来配置Google App Engine