美文网首页
jetpack组件的使用入门

jetpack组件的使用入门

作者: Peakmain | 来源:发表于2020-07-06 15:20 被阅读0次

Lifecycle

  • 添加依赖
    def lifecycle_version = "2.2.0"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
  • 管理fragment和activity的生命周期
    OnLifecycleEvent注解表示监听哪个生命周期
  • 使用
class LifecycleObserver : LifecycleObserver {
    private val TAG = LifecycleObserver::class.simpleName

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun create() {
        Log.e(TAG, "LifecycleObserver->onCreate")
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun start(){
        Log.e(TAG, "LifecycleObserver->onStart")
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun resume(){
        Log.e(TAG, "LifecycleObserver->onResume")
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop(){
        Log.e(TAG, "LifecycleObserver->onStop")
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun destory(){
        Log.e(TAG, "LifecycleObserver->onDestory")
    }
}

activity中使用

class MainActivity : AppCompatActivity(){
    protected override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val observer=LifecycleObserver()
        lifecycle.addObserver(observer)
    }
}

使用很简单,实际就是用一个类统一管理了activity或者fragment的生命周期

ViewModel

  • ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据
  • 使用
class MainViewModel : ViewModel() {
    var number = 0
}

activity的代码

    lateinit var mainViewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mainViewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        value.text= mainViewModel.number.toString()
        button1.setOnClickListener {
            mainViewModel.number++
            value.text = mainViewModel.number.toString()
        }
        button2.setOnClickListener{
            mainViewModel.number--
            value.text = mainViewModel.number.toString()
        }
    }

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="0"
        android:textSize="18sp" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:text="加" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:text="减" />


</LinearLayout>

LiveData

  • 在底层数据库更改时通知视图(实际是观察者和被观察者)
  • 使用
class MainViewModel : ViewModel() {
    private var numbers: MutableLiveData<Int>? = null

    fun getNumber(): MutableLiveData<Int>? {
        if (numbers == null) {
            numbers = MutableLiveData()
            numbers!!.value = 0
        }
        return numbers
    }

    fun addNumber(data: Int) {
        numbers?.value = numbers?.value?.plus(data)
    }
}
    lateinit var mainViewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mainViewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        mainViewModel.getNumber()?.observe(this, Observer {
            value.text = it.toString()
        })
        button1.setOnClickListener {
            mainViewModel.addNumber(1)
        }
        button2.setOnClickListener {
            mainViewModel.addNumber(-1)
        }
    }

DataBinding

需要在build.gradle中的 defaultConfig添加以下代码

   dataBinding {
            enabled true
        }

修改布局

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
       <variable
           name="data"
           type="com.peakmain.jetpack.MainViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@{String.valueOf(data.number)}"
            android:textSize="18sp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:onClick="@{()->data.addNumber(1)}"
            android:text="加" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:onClick="@{()->data.addNumber(-1)}"
            android:text="减" />


    </LinearLayout>
</layout>

MainViewModel管理界面中的数据

class MainViewModel : ViewModel() {
    private var number: MutableLiveData<Int>? = null
    fun getNumber(): MutableLiveData<Int> {
        if (number == null) {
            number = MutableLiveData()
            number!!.value = 0
        }
        return number!!
    }

    fun addNumber(data: Int) {
        number!!.value = number!!.value!! + data
    }
}

activity的使用

    lateinit var binding: ActivityMainBinding
    private lateinit var mainViewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        mainViewModel=ViewModelProviders.of(this).get(MainViewModel::class.java)//创建mainViewModel
        binding.data = mainViewModel
        binding.lifecycleOwner = this
    }

ViewModelSavedState

即使进程在后台被系统杀死数据也存活
修改MainViewModel

class MainViewModel(state: SavedStateHandle) : ViewModel() {
    private val handle: SavedStateHandle = state

    companion object {
        const val KEY_NUMBER = "key_number"
    }

    fun getNumber(): MutableLiveData<Int> {
        if (!handle.contains(KEY_NUMBER)) {
            handle.set(KEY_NUMBER, 0)
        }
        return handle.getLiveData(KEY_NUMBER)
    }

    fun addNumber(data: Int) {
        getNumber().value = getNumber().value!!.plus(data)
    }

}

activity中修改mainViewModel

 mainViewModel = ViewModelProvider(this, SavedStateViewModelFactory(this.application, this)).get(MainViewModel::class.java)

AndroidViewModel

方便传context
修改mainViewModel

class MainViewModel(application: Application,state: SavedStateHandle) : AndroidViewModel(application) {
    private val handle: SavedStateHandle = state
    private val context: Application = application

    companion object {
        const val KEY_NUMBER = "key_number"
    }

    fun getNumber(): MutableLiveData<Int> {
        if (!handle.contains(KEY_NUMBER)) {
            handle.set(KEY_NUMBER, 0)
        }
        return handle.getLiveData(KEY_NUMBER)
    }

    fun addNumber(data: Int) {
        getNumber().value = getNumber().value!!.plus(data)
    }

    fun startActivity() {
        val intent=Intent(context, MainActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        context.startActivity(intent)
    }
}

Room

  • 持久性库在 SQLite 的基础上提供了一个抽象层
  • 添加依赖
  apply plugin: 'kotlin-kapt'
    def room_version = "2.2.5"

    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation "androidx.room:room-ktx:$room_version"
    // Test helpers
    testImplementation "androidx.room:room-testing:$room_version"

Entity、Dao、Database
使用 @Database 注释的类应满足以下条件:

  • 是扩展 RoomDatabase 的抽象类。
  • 在注释中添加与数据库关联的实体列表。
  • 包含具有 0 个参数且返回使用 @Dao 注释的类的抽象方法。

Entity表示数据库中的表,Dao包含用于访问数据库的方法

@Entity
class Word() {

    @PrimaryKey(autoGenerate = true)
     var id: Int = 0
    @ColumnInfo(name = "english_word")
    var word: String = ""
    @ColumnInfo(name = "chinese_mean")
    var chineseMean: String = ""

    constructor(word: String, chineseMean: String) : this() {
        this.word = word
        this.chineseMean=chineseMean
    }
}
  • Dao包含用于访问数据库的方法
@Dao
interface WordDao {
    @Insert
    fun insertWord(vararg words: Word?)

    @Update
    fun updateWord(vararg words: Word?)

    @Delete
    fun deleteWord(vararg words: Word?)

    @Query("DELETE FROM WORD")
    fun deleteAllWords()

    @Query("SELECT *FROM WORD ORDER BY ID DESC ")
    fun getAllWords():List<Word>

}
  • Database
@Database(entities = [Word::class], version = 1, exportSchema = false)
abstract class WordDatabase : RoomDatabase() {
    abstract fun getWordDao(): WordDao
}

activity的使用

class MainActivity : AppCompatActivity() {
    lateinit var wordDatabase: WordDatabase
    lateinit var wordDao: WordDao
    lateinit var binding: ActivityMainBinding
    private lateinit var mainViewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        mainViewModel = ViewModelProvider(this, SavedStateViewModelFactory(this.application, this)).get(MainViewModel::class.java)
        binding.data = mainViewModel
        binding.lifecycleOwner = this
        wordDatabase = Room.databaseBuilder(this, WordDatabase::class.java, "word_database")
                .allowMainThreadQueries()
                .build()
        wordDao = wordDatabase.getWordDao()
        updateView()
    }
    //更新view
    fun updateView() {
        val list = wordDao.getAllWords()
        var test = ""
        for (word in list) {
            test = test + word.id + ":" + word.word + "=" + word.chineseMean + "\n"
        }
        value.text = test
    }
    //添加数据
    fun add(view: View) {
        val word = Word("peakmain", "皮克曼")
        val word1 = Word("body", "宝宝")
        wordDao.insertWord(word, word1)
        updateView()
    }
   //更新
    fun update(view: View) {
        val word = Word("Treasure", "喜")
        word.id = 1
        wordDao.updateWord(word)
        updateView()
    }
}

代码修改一
问题:1、会存在多个对象的实体类
2、mainviewmodel实际应该只是管理数据而不负责创建数据和删除数据等功能

  • WordDatabase单例
@Database(entities = [Word::class], version = 1, exportSchema = false)
abstract class WordDatabase : RoomDatabase() {
    companion object {
        private var INSTANCE: WordDatabase? = null

        fun getInstance(context: Context): WordDatabase {
            if (INSTANCE == null) {
                synchronized(this) {
                    if (INSTANCE == null) {
                        INSTANCE = Room.databaseBuilder(context.applicationContext
                                , WordDatabase::class.java, "word_database")
                                .build()

                    }
                }
            }
            return INSTANCE!!
        }
    }

    abstract fun getWordDao(): WordDao
}
  • 修改wordDao里面获取数据
    @Query("SELECT *FROM WORD ORDER BY ID DESC ")
    fun getAllWords():LiveData<List<Word>>
  • 建立仓库
    我们会发现一个问题:ViewModel的作用是和管理界面相关的数据,所以插入数据、更新数据和获取数据我们应该放到一个仓库里面
class WordRepository(context: Context) {
    val wordDatabase: WordDatabase = WordDatabase.getInstance(context.applicationContext)
    val wordDao = wordDatabase.getWordDao()
    val allWordsLive: LiveData<List<Word>> = wordDao.getAllWords()


    fun insertWords(vararg word: Word) {
        InsertAsyncTask(wordDao).execute(*word)
    }

    fun updateWord(vararg word: Word) {
        UpdateAsyncTask(wordDao).execute(*word)
    }

    class InsertAsyncTask(private val wordDao: WordDao) : AsyncTask<Word, Void, Void>() {

        override fun doInBackground(vararg p0: Word): Void? {
            wordDao.insertWord(*p0)
            return null
        }

    }

    class UpdateAsyncTask(private val wordDao: WordDao) : AsyncTask<Word, Void, Void>() {

        override fun doInBackground(vararg p0: Word): Void? {
            wordDao.updateWord(*p0)
            return null
        }

    }
}
  • MainViewModel代码修改
class MainViewModel(application: Application) : AndroidViewModel(application) {
    private val context: Application = application
    var wordRepository: WordRepository = WordRepository(application)
    fun getAllWordsLive(): LiveData<List<Word>> {
        return wordRepository.allWordsLive
    }

    fun insertWords(vararg word: Word) {
        wordRepository.insertWords(*word)
    }

    fun updateWord(vararg word: Word) {
        wordRepository.updateWord(*word)
    }


    fun startActivity() {
        val intent = Intent(context, MainActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        context.startActivity(intent)
    }
}
  • mainActivity代码修改
class MainActivity : AppCompatActivity() {
    lateinit var wordDao: WordDao
    lateinit var binding: ActivityMainBinding
    private lateinit var mainViewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        mainViewModel =
                ViewModelProvider(this, SavedStateViewModelFactory(this.application, this))
                        .get(MainViewModel::class.java)
        binding.data = mainViewModel
        binding.lifecycleOwner = this
        mainViewModel.getAllWordsLive().observe(this, Observer<List<Word>> { t ->
            var test = ""
            for (word in t) {
                test = test + word.id + ":" + word.word + "=" + word.chineseMean + "\n"
            }
            value.text = test
        })
    }

    //添加数据
    fun add(view: View) {
        val word1 = Word("peakmain", "皮克曼")
        val word2 = Word("body", "宝宝")
        mainViewModel.insertWords(word1,word2)
    }

    //更新
    fun update(view: View) {
        val word = Word("Treasure", "喜")
        word.id = 3
        mainViewModel.updateWord(word)
    }
}

迁移表结构

  • word修改
    @ColumnInfo(name = "showChinese")
    var showChinese: Boolean = false
  • WordDatabase
@Database(entities = [Word::class], version = 2, exportSchema = false)
abstract class WordDatabase : RoomDatabase() {
    companion object {
        private var INSTANCE: WordDatabase? = null

        fun getInstance(context: Context): WordDatabase {
            if (INSTANCE == null) {
                synchronized(this) {
                    if (INSTANCE == null) {
                        INSTANCE = Room.databaseBuilder(context.applicationContext
                                , WordDatabase::class.java, "word_database")
                                .addMigrations(migration1_2)
                                .build()

                    }
                }
            }
            return INSTANCE!!
        }
    }

    abstract fun getWordDao(): WordDao
}

object migration1_2 : Migration(1,2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE word ADD COLUMN showChinese INTEGER NOT NULL DEFAULT 1")
    }
}

删除数据库中某个字段
删除数据库中某个字段步骤

  • 1、创建新表
  • 2、从旧表中插入数据
  • 3、删除旧表
  • 4、修改表名为旧表表名
object migration2_3 : Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.run {
            execSQL("CREATE TABLE word_tmp (id INTEGER PRIMARY KEY NOT NULL,english_word TEXT," +
                    "chinese_mean TEXT)")
            execSQL("INSERT INTO word_tmp (id,english_word,chinese_mean) " +
                    "SELECT id,english_word,chinese_mean from word")
            execSQL("DROP TABLE word")

            execSQL("ALTER TABLE word_tmp RENAME to word")
        }
    }
}

WorkManager

使用 WorkManager API 可以轻松地调度即使在应用退出或设备重启时仍应运行的可延迟异步任务

   def work_version = "2.3.4"
    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"
    // optional - GCMNetworkManager support
    implementation "androidx.work:work-gcm:$work_version"
    // optional - Test helpers
    androidTestImplementation "androidx.work:work-testing:$work_version"
class MyWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters)
    : Worker(context, workerParams) {
    override fun doWork(): Result {
        val value = inputData.getString("in_key")
        Log.e("TAG", "value = $value")
        Log.e("TAG", "开始睡眠")
        Thread.sleep(3000)
        Log.e("TAG", "结束睡眠")
        return Result.success(workDataOf("out_key" to "$value result"))
    }
}
        val constraints = Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)//👈设置条件为网络连接情况
                .build()
        val workReuest =
                OneTimeWorkRequestBuilder<MyWork>()
                        //.setConstraints(constraints)//👈设置条件
                        .setInputData(workDataOf("in_key" to "Peakmain"))//👈输入简单数据
                        .build()
        workManager.enqueue(workReuest)
     //监听数据变化
        workManager.getWorkInfoByIdLiveData(workReuest.id)
                .observe(this, Observer {
                    Log.e("TAG", "onCreate:" + it.state)
                    if (it.state == WorkInfo.State.SUCCEEDED) {
                        Log.e("TAG", "onCreate" + it.outputData.getString("out_key"))
                    }
                })

相关文章

网友评论

      本文标题:jetpack组件的使用入门

      本文链接:https://www.haomeiwen.com/subject/xdesqktx.html