Browse Source

+ 扩展协程Flow, 便于使用ROOM数据库框架
+ 扩展ViewModel扩展函数, 便于意外销毁, 屏幕旋转等情况恢复数据

drake 5 years ago
parent
commit
6333df9b82

+ 1 - 1
README.md

@@ -83,7 +83,7 @@ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'
 // 支持自动下拉刷新和缺省页的, 可选, 刷新头和上拉加载参考SmartRefreshLayout
 implementation 'com.github.liangjingkanji:BRV:1.2.1'
 
-implementation 'com.github.liangjingkanji:Net:2.1.5'
+implementation 'com.github.liangjingkanji:Net:2.1.6'
 ```
 
 

+ 1 - 0
build.gradle

@@ -8,6 +8,7 @@ buildscript {
         brv_version = '1.2.12'
         coroutine_version = '1.3.0'
         glide_version = '4.9.0'
+        room_version = "2.2.3"
     }
 
     repositories {

+ 1 - 0
net/build.gradle

@@ -48,6 +48,7 @@ dependencies {
     compileOnly "com.github.liangjingkanji:BRV:$brv_version"
     compileOnly "com.github.bumptech.glide:glide:$glide_version"
 
+    api 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
 
     compileOnly "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
     compileOnly "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"

+ 79 - 0
net/src/main/java/com/drake/net/utils/JetPackUtils.kt

@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved.
+ * Project:Net
+ * Author:Drake
+ * Date:2/15/20 4:30 AM
+ */
+
+package com.drake.net.utils
+
+import android.database.Cursor
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.*
+import com.drake.net.scope.AndroidScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.distinctUntilChanged
+
+/**
+ * 迭代Cursor
+ */
+fun Cursor.foreach(block: Cursor.() -> Unit) {
+    if (count == 0) {
+        close()
+        return
+    }
+    moveToFirst()
+    do {
+        block()
+    } while (moveToNext())
+    close()
+}
+
+/**
+ * 观察LiveData
+ */
+fun <M> LifecycleOwner.observe(liveData: LiveData<M>?, block: M?.() -> Unit) {
+    liveData?.observe(this, Observer { it.block() })
+}
+
+/**
+ * 监听数据库
+ */
+@UseExperimental(ExperimentalCoroutinesApi::class)
+fun <T> Flow<List<T>>.listen(
+    lifecycleOwner: LifecycleOwner? = null,
+    lifeEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY,
+    block: (List<T>) -> Unit
+) {
+    AndroidScope(lifecycleOwner, lifeEvent).launch {
+        distinctUntilChanged().collect { data ->
+            withMain {
+                block(data)
+            }
+        }
+    }
+}
+
+open class SavedViewModel(var saved: SavedStateHandle) : ViewModel()
+
+inline fun <reified M : ViewModel> ViewModelStoreOwner.getViewModel(): M {
+    return ViewModelProvider(this).get(M::class.java)
+}
+
+inline fun <reified M : ViewModel> FragmentActivity.getSavedModel(): M {
+    return ViewModelProvider(
+        this,
+        SavedStateViewModelFactory(application, this)
+    ).get(M::class.java)
+}
+
+
+inline fun <reified M : ViewModel> Fragment.getSavedModel(): M {
+    return ViewModelProvider(
+        this,
+        SavedStateViewModelFactory(activity!!.application, this)
+    ).get(M::class.java)
+}

+ 0 - 17
net/src/main/java/com/drake/net/utils/SuspendUtils.kt

@@ -11,7 +11,6 @@ import android.os.Handler
 import android.os.Looper
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.supervisorScope
 import kotlinx.coroutines.withContext
 
 
@@ -31,22 +30,6 @@ suspend fun <T> withUnconfined(block: suspend CoroutineScope.() -> T) =
 
 // </editor-fold>
 
-/**
- * 允许抛出任何异常的作用域, 不会导致父协程取消和崩溃
- */
-suspend fun tryScope(
-    error: suspend CoroutineScope.(Throwable) -> Unit = { it.printStackTrace() },
-    block: suspend CoroutineScope.() -> Unit
-) {
-    return supervisorScope {
-        try {
-            block()
-        } catch (e: Exception) {
-            error(e)
-        }
-    }
-}
-
 /**
  * 在主线程运行
  */

+ 40 - 0
net/src/main/java/com/drake/net/utils/ThrottleClickListener.kt

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved.
+ * Project:Net
+ * Author:Drake
+ * Date:2/15/20 8:20 PM
+ */
+
+package com.drake.net.utils
+
+import android.view.View
+import java.util.concurrent.TimeUnit
+
+internal fun View.throttleClick(
+    interval: Long = 500,
+    unit: TimeUnit = TimeUnit.MILLISECONDS,
+    block: View.() -> Unit
+) {
+    setOnClickListener(ThrottleClickListener(interval, unit, block))
+}
+
+internal class ThrottleClickListener(
+    private val interval: Long = 500,
+    private val unit: TimeUnit = TimeUnit.MILLISECONDS,
+    private var block: View.() -> Unit
+) :
+    View.OnClickListener {
+
+    private var lastTime: Long = 0
+
+    override fun onClick(v: View) {
+
+        val currentTime = System.currentTimeMillis()
+
+        if (currentTime - lastTime > unit.toMillis(interval)) {
+            lastTime = currentTime
+            block(v)
+        }
+
+    }
+}

+ 7 - 3
sample/build.gradle

@@ -30,7 +30,7 @@ dependencies {
     implementation fileTree(dir: "libs", include: ["*.jar"])
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
     implementation "androidx.appcompat:appcompat:1.1.0"
-    implementation "androidx.core:core-ktx:1.1.0"
+    implementation "androidx.core:core-ktx:1.2.0"
     implementation "androidx.constraintlayout:constraintlayout:1.1.3"
     testImplementation "junit:junit:4.13"
     androidTestImplementation "androidx.test:runner:1.2.0"
@@ -39,7 +39,7 @@ dependencies {
     implementation project(path: ":net")
 
     implementation "androidx.recyclerview:recyclerview:1.1.0"
-    implementation "com.google.android.material:material:1.0.0"
+    implementation "com.google.android.material:material:1.1.0"
 
 
     implementation "com.github.liangjingkanji:BRV:$brv_version"
@@ -56,4 +56,8 @@ dependencies {
 
     implementation "com.github.liangjingkanji:debugkit:1.2.9"
     implementation "com.github.liangjingkanji:LogCat:1.0"
-}
+
+    implementation "androidx.room:room-runtime:$room_version"
+    kapt "androidx.room:room-compiler:$room_version"
+    implementation "androidx.room:room-ktx:$room_version"
+}

+ 3 - 2
sample/src/main/AndroidManifest.xml

@@ -4,15 +4,16 @@
     package="com.drake.net.sample">
 
     <application
-        android:allowBackup="true"
         android:name=".App"
+        android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
         android:theme="@style/AppTheme"
         tools:ignore="GoogleAppIndexingWarning">
-        <activity android:name=".MainActivity">
+        <activity android:name=".ui.activity.Main2Activity"></activity>
+        <activity android:name=".ui.activity.MainActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 

+ 10 - 1
sample/src/main/java/com/drake/net/sample/Model.kt

@@ -1,3 +1,12 @@
 package com.drake.net.sample
 
-class Model
+import androidx.lifecycle.SavedStateHandle
+import com.drake.net.utils.SavedViewModel
+
+class Model(saved: SavedStateHandle) : SavedViewModel(saved) {
+    var name: String?
+        get() = saved.get("name")
+        set(value) {
+            saved["name"] = value
+        }
+}

+ 20 - 0
sample/src/main/java/com/drake/net/sample/ui/activity/Main2Activity.kt

@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved.
+ * Project:Net
+ * Author:Drake
+ * Date:2/15/20 5:36 PM
+ */
+
+package com.drake.net.sample.ui.activity
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import com.drake.net.sample.R
+
+class Main2Activity : AppCompatActivity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_main2)
+    }
+}

+ 10 - 5
sample/src/main/java/com/drake/net/sample/MainActivity.kt → sample/src/main/java/com/drake/net/sample/ui/activity/MainActivity.kt

@@ -1,8 +1,16 @@
-package com.drake.net.sample
+/*
+ * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved.
+ * Project:Net
+ * Author:Drake
+ * Date:1/18/20 4:41 PM
+ */
+
+package com.drake.net.sample.ui.activity
 
 import android.os.Bundle
 import androidx.appcompat.app.AppCompatActivity
 import com.drake.net.get
+import com.drake.net.sample.R
 import com.drake.net.utils.scope
 import kotlinx.android.synthetic.main.activity_main.*
 
@@ -14,13 +22,10 @@ class MainActivity : AppCompatActivity() {
 
         setContentView(R.layout.activity_main)
 
-
         content.onRefresh {
 
             scope {
-                val data =
-                    get<String>("https://github.com/liangjingkanji")
-
+                val data = get<String>("https://github.com/liangjingkanji")
                 textView.text = data.await()
             }
 

+ 14 - 0
sample/src/main/res/layout/activity_main2.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2018, Umbrella CompanyLimited All rights reserved.
+  ~ Project:Net
+  ~ Author:Drake
+  ~ Date:2/15/20 5:36 PM
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ui.activity.Main2Activity">
+
+</androidx.constraintlayout.widget.ConstraintLayout>