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
   }
  • 使用

    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) } }
     
     
    
    
   
   
  
  

最后来个效果展示:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值