Google Architecture Components 使用

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>

这里写图片描述
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
   }
  • 使用
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
}
  • 使用
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)
    }
}

最后来个效果展示:

这里写图片描述

相关文章
相关标签/搜索