欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Google Architecture Components 使用

程序员文章站 2022-06-16 16:48:16
...

architecture components使用google新推出的Android 架构组件,目标是帮助我们设计更好、可测试和可维护应用程序。它可以自动管理UI组件生命周期,也能处理数据持久化的问题。

现在的稳定版本是1.0
官网地址
Demo项目地址

环境

  • 编译器: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>

Google Architecture Components 使用
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 Architecture Components 使用