Skip to content

Commit

Permalink
v1.0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamKwokX committed Sep 13, 2023
1 parent 3abe582 commit 94c8fa4
Show file tree
Hide file tree
Showing 44 changed files with 147 additions and 84 deletions.
2 changes: 1 addition & 1 deletion api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ tasks.withType(KotlinCompile).configureEach{
// publish
mavenPublishing {
def artifactId = "mvb-android"
def version = "1.0.4"
def version = "1.0.5"
def isSnapshot = false

if (isSnapshot) version += "-SNAPSHOT"
Expand Down
6 changes: 4 additions & 2 deletions api/src/androidTest/java/pers/shawxingkwok/mvb/MyFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
package pers.shawxingkwok.mvb

import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import pers.shawxingkwok.mvb.android.*
import pers.shawxingkwok.mvb.android.observe
import pers.shawxingkwok.mvb.android.rmb
import pers.shawxingkwok.mvb.android.saveMutableStateFlow
import pers.shawxingkwok.mvb.android.transform

internal class MyFragment : Fragment() {
val arr by rmb { intArrayOf(1, 2) }
Expand Down
22 changes: 20 additions & 2 deletions api/src/main/java/pers/shawxingkwok/mvb/android/Saver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.os.Parcel
import android.os.Parcelable
import pers.shawxingkwok.ktutil.updateIf
import kotlin.reflect.KClass

internal class Saver(
var value: Any?,
Expand All @@ -21,8 +22,21 @@ internal class Saver(
}

companion object CREATOR : Parcelable.Creator<Saver> {
var parcelableLoader: ClassLoader? = null
var recover: ((Any?) -> Any?)? = null
private var parcelableComponent: KClass<out Parcelable>? = null
private var parcelableLoader: ClassLoader? = null
private var recover: ((Any?) -> Any?)? = null

fun prepare(parcelableComponent: KClass<out Parcelable>?, recover: ((Any?) -> Any?)?){
this.parcelableComponent = parcelableComponent
parcelableLoader = parcelableComponent?.java?.classLoader
this.recover = recover
}

fun clear(){
parcelableComponent = null
parcelableLoader = null
recover = null
}

override fun createFromParcel(parcel: Parcel): Saver {
@SuppressLint("ParcelClassLoader")
Expand All @@ -33,6 +47,10 @@ internal class Saver(
UNINITIALIZED
else
parcel.readValue(parcelableLoader)
// convert Parcelable[] to the actual.
// However, the inner Parcelable[] can't be parsed here.
// This problem could only be fixed by the authority.
.convertParcelableArrayIfNeeded(parcelableComponent)
.updateIf({ recover != null }){ recover!!(it) }

return Saver(value)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package pers.shawxingkwok.mvb.android

import android.os.Parcelable
import java.util.*
import kotlin.reflect.KClass

@Suppress("UNCHECKED_CAST")
@PublishedApi
internal fun <T> T.convertParcelableArrayIfNeeded(parcelableComponent: KClass<out Parcelable>?): T =
if (this is Array<*> && javaClass.componentType == Parcelable::class.java) {
requireNotNull(parcelableComponent){
"The parcelable component misses."
}
val newArrClass = java.lang.reflect.Array.newInstance(parcelableComponent.java, size).javaClass as Class<out Array<*>>
Arrays.copyOf(this, size, newArrClass) as T
}
else
this
1 change: 0 additions & 1 deletion api/src/main/java/pers/shawxingkwok/mvb/android/observe.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package pers.shawxingkwok.mvb.android

import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
Expand Down
43 changes: 26 additions & 17 deletions api/src/main/java/pers/shawxingkwok/mvb/android/save.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ import java.io.Serializable
import java.util.*
import kotlin.reflect.KClass

@PublishedApi
internal val KClass<*>.parcelableComponent: KClass<out Parcelable>? get() {
fun Class<*>.isParcelable(): Boolean =
Parcelable::class.java.isAssignableFrom(this)

return if (this.java.isParcelable())
this as KClass<out Parcelable>
else
java.componentType?.takeIf { it.isParcelable() }?.kotlin as KClass<out Parcelable>?
}

public class SavableMVBData<LV, T, C> @PublishedApi internal constructor(
public var parcelableComponent: KClass<out Parcelable>?,
@PublishedApi internal var savedType: KClass<C & Any>,
Expand All @@ -29,36 +40,27 @@ public class SavableMVBData<LV, T, C> @PublishedApi internal constructor(
when(val bundle = state.get<Bundle>(key)){
null -> Saver(UNINITIALIZED, convert).also { state[key] = bundleOf("" to it) }
else -> {
Saver.parcelableLoader = (parcelableComponent ?: savedType.parcelableComponent)?.java?.classLoader
Saver.recover = recover
Saver.prepare(
parcelableComponent = parcelableComponent ?: savedType.parcelableComponent,
recover = recover,
)

val saver =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
bundle.getParcelable("", Saver::class.java)!!
else
bundle.getParcelable("")!!

Saver.recover = null
// update [convert] to remove any possible references to old [thisRef].
Saver.clear()

// update [convert] to remove any possible reference to old [thisRef].
saver.convert = convert
saver
}
}
}
}

@PublishedApi
internal val KClass<*>.parcelableComponent: KClass<out Parcelable>? get(){
if (Parcelable::class.java.isAssignableFrom(this.java))
return this as KClass<out Parcelable>

val component = java.componentType ?: return null
if (Parcelable::class.java.isAssignableFrom(component))
return component.kotlin as KClass<out Parcelable>

return null
}

/**
* See [doc](https://shawxingkwok.github.io/ITWorks/docs/multiplatform/mvb/android/#save).
*/
Expand Down Expand Up @@ -122,6 +124,7 @@ public inline fun <LV, reified T> LV.saveMutableStateFlow(
/**
* See [doc](https://shawxingkwok.github.io/ITWorks/docs/multiplatform/mvb/android/#save).
*/
@Suppress("NAME_SHADOWING")
public inline fun <LV, reified T> LV.saveMutableSharedFlow(
parcelableComponent: KClass<out Parcelable>? = null,
replay: Int = 0,
Expand All @@ -139,10 +142,16 @@ public inline fun <LV, reified T> LV.saveMutableSharedFlow(
convert = { it.replayCache },
recover = { cache ->
val flow = MutableSharedFlow<T>(replay, extraBufferCapacity, onBufferOverflow)
cache.forEach(flow::tryEmit)

val parcelableComponent = parcelableComponent ?: T::class.parcelableComponent

cache.map{ it.convertParcelableArrayIfNeeded(parcelableComponent) }
.forEach(flow::tryEmit)

flow
}
)
// This part is essential.
.also {
if (it.parcelableComponent == null)
it.parcelableComponent = T::class.parcelableComponent
Expand Down
3 changes: 2 additions & 1 deletion demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ dependencies {
implementation libs.viewbindingKtx

testImplementation libs.junit
androidTestImplementation libs.kotlin.reflect
androidTestImplementation(libs.androidx.fragment.test)
androidTestImplementation libs.androidx.test.ext.junit
androidTestImplementation libs.espresso.core
androidTestImplementation libs.kotlin.reflect
}

//region shawxingkwok: mvb
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
8
12
0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified demo/build/kotlin/compileDebugKotlin/cacheable/last-build.bin
Binary file not shown.
Binary file modified demo/build/kotlin/compileDebugKotlin/local-state/build-history.bin
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@file:Suppress("unused")

package pers.shawxingkwok.androidutil.view

import android.os.Parcelable
import android.util.SparseArray
import androidx.fragment.app.Fragment
import kotlinx.parcelize.Parcelize
import pers.shawxingkwok.mvb.android.save

internal class ParcelableComponent {
internal class MyFragment : Fragment() {
@Parcelize
data class User(val id: Long, val name: String): Parcelable

/**
* Pass `KClass<out Parcelable>` (`User::class` in this case) when ultimately
* saved as `List<out Parcelable>`/`SparseArray<out Parcelable>`.
*
* 'ultimately' means saved types change with `transform`.
*/
val userList by save(User::class) { mutableListOf<User>() }
val userSparseArr by save(User::class) { SparseArray<User>() }

/**
* `User::class` could be automatically recognized in cases below.
*/
var user: User by save()
var userArr by save { emptyArray<User>() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@ package pers.shawxingkwok.androidutil.view
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.switchMap
import pers.shawxingkwok.mvb.android.rmb
import pers.shawxingkwok.mvb.android.save
import pers.shawxingkwok.mvb.android.saveMutableLiveData

fun getFilteredData(query: String): LiveData<List<String>> {
TODO()
}

class SaveLiveData{
class MyViewModel(private val state: SavedStateHandle) : ViewModel(){
val filteredData: LiveData<List<String>> =
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions restoretest/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ dependencies {

dependencies {
implementation(project(":api"))
// implementation("io.github.shawxingkwok:mvb-android:1.0.5")
implementation(libs.bundles.shawxing)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package pers.shawxingkwok.restoretest

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
Expand All @@ -17,8 +13,5 @@ import org.junit.Assert.*
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("pers.shawxingkwok.restoretest", appContext.packageName)
}
}
Loading

0 comments on commit 94c8fa4

Please sign in to comment.