This repository has been archived by the owner on Mar 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from cheonjaewoong/nullable-notnull-property
Add not-null property delegate
- Loading branch information
Showing
7 changed files
with
322 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
savedstate-ktx/src/androidTest/java/io/woong/savedstate/NotNullPropertyDelegatorTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package io.woong.savedstate | ||
|
||
import android.content.Context | ||
import androidx.activity.ComponentActivity | ||
import androidx.activity.viewModels | ||
import androidx.lifecycle.SavedStateHandle | ||
import androidx.lifecycle.ViewModel | ||
import androidx.test.core.app.ApplicationProvider | ||
import androidx.test.core.app.launchActivity | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import com.google.common.truth.Truth.assertThat | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
public class NotNullPropertyDelegatorTest { | ||
private lateinit var context: Context | ||
|
||
@Before | ||
public fun init() { | ||
context = ApplicationProvider.getApplicationContext() | ||
} | ||
|
||
@Test | ||
public fun notNullWithInitialValue() { | ||
val scenario = launchActivity<TestActivity>() | ||
scenario.onActivity { activity -> | ||
val viewModel = activity.viewModel | ||
assertThat(viewModel.notNullValue).isEqualTo("a") | ||
assertThat(viewModel.notNullVariable).isEqualTo("b") | ||
|
||
viewModel.notNullVariable = "c" | ||
assertThat(viewModel.notNullVariable).isEqualTo("c") | ||
} | ||
} | ||
|
||
@Test | ||
public fun stateSaving() { | ||
val scenario = launchActivity<TestActivity>() | ||
scenario.onActivity { activity -> | ||
val viewModel = activity.viewModel | ||
viewModel.notNullVariable = "bbb" | ||
|
||
assertThat(viewModel.notNullValue).isEqualTo("a") | ||
assertThat(viewModel.notNullVariable).isEqualTo("bbb") | ||
} | ||
scenario.recreate() | ||
scenario.onActivity { activity -> | ||
val viewModel = activity.viewModel | ||
assertThat(viewModel.notNullValue).isEqualTo("a") | ||
assertThat(viewModel.notNullVariable).isEqualTo("bbb") | ||
} | ||
} | ||
|
||
public class TestActivity : ComponentActivity() { | ||
public val viewModel: TestViewModel by viewModels() | ||
} | ||
|
||
public class TestViewModel(savedStateHandle: SavedStateHandle) : ViewModel() { | ||
public val notNullValue: String by savedStateHandle.notNull("a") | ||
public var notNullVariable: String by savedStateHandle.notNull("b") | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
savedstate-ktx/src/androidTest/java/io/woong/savedstate/NullablePropertyDelegatorTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package io.woong.savedstate | ||
|
||
import android.content.Context | ||
import androidx.activity.ComponentActivity | ||
import androidx.activity.viewModels | ||
import androidx.lifecycle.SavedStateHandle | ||
import androidx.lifecycle.ViewModel | ||
import androidx.test.core.app.ApplicationProvider | ||
import androidx.test.core.app.launchActivity | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import com.google.common.truth.Truth.assertThat | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
public class NullablePropertyDelegatorTest { | ||
private lateinit var context: Context | ||
|
||
@Before | ||
public fun init() { | ||
context = ApplicationProvider.getApplicationContext() | ||
} | ||
|
||
@Test | ||
public fun simplestDelegate() { | ||
val scenario = launchActivity<TestActivity>() | ||
scenario.onActivity { activity -> | ||
val viewModel = activity.viewModel | ||
assertThat(viewModel.simpleValue).isNull() | ||
assertThat(viewModel.simpleVariable).isNull() | ||
|
||
viewModel.simpleVariable = "test" | ||
assertThat(viewModel.simpleVariable).isEqualTo("test") | ||
} | ||
} | ||
|
||
@Test | ||
public fun nullableWithInitialValue() { | ||
val scenario = launchActivity<TestActivity>() | ||
scenario.onActivity { activity -> | ||
val viewModel = activity.viewModel | ||
assertThat(viewModel.initializedValue).isEqualTo("a") | ||
assertThat(viewModel.initializedVariable).isEqualTo("b") | ||
|
||
viewModel.initializedVariable = "c" | ||
assertThat(viewModel.initializedVariable).isEqualTo("c") | ||
} | ||
} | ||
|
||
@Test | ||
public fun stateSaving() { | ||
val scenario = launchActivity<TestActivity>() | ||
scenario.onActivity { activity -> | ||
val viewModel = activity.viewModel | ||
viewModel.simpleVariable = "aaa" | ||
viewModel.initializedVariable = "bbb" | ||
|
||
assertThat(viewModel.simpleValue).isNull() | ||
assertThat(viewModel.simpleVariable).isEqualTo("aaa") | ||
assertThat(viewModel.initializedValue).isEqualTo("a") | ||
assertThat(viewModel.initializedVariable).isEqualTo("bbb") | ||
} | ||
scenario.recreate() | ||
scenario.onActivity { activity -> | ||
val viewModel = activity.viewModel | ||
assertThat(viewModel.simpleValue).isNull() | ||
assertThat(viewModel.simpleVariable).isEqualTo("aaa") | ||
assertThat(viewModel.initializedValue).isEqualTo("a") | ||
assertThat(viewModel.initializedVariable).isEqualTo("bbb") | ||
} | ||
} | ||
|
||
public class TestActivity : ComponentActivity() { | ||
public val viewModel: TestViewModel by viewModels() | ||
} | ||
|
||
public class TestViewModel(savedStateHandle: SavedStateHandle) : ViewModel() { | ||
public val simpleValue: String? by savedStateHandle | ||
public var simpleVariable: String? by savedStateHandle | ||
|
||
public val initializedValue: String? by savedStateHandle.nullable("a") | ||
public var initializedVariable: String? by savedStateHandle.nullable("b") | ||
} | ||
} |
94 changes: 0 additions & 94 deletions
94
savedstate-ktx/src/androidTest/java/io/woong/savedstate/PropertyDelegatorTest.kt
This file was deleted.
Oops, something went wrong.
62 changes: 62 additions & 0 deletions
62
savedstate-ktx/src/main/java/io/woong/savedstate/NotNullPropertyDelegates.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package io.woong.savedstate | ||
|
||
import androidx.lifecycle.SavedStateHandle | ||
import kotlin.reflect.KProperty | ||
|
||
/** | ||
* Returns a property delegate for reading and writing a not-null value into [SavedStateHandle] | ||
* with initial value. | ||
* | ||
* Reading the property equals to read value from [SavedStateHandle] | ||
* and writing equals to write value to [SavedStateHandle]. | ||
* | ||
* To define not-null property delegate, use `by` keyword of Kotlin: | ||
* The property must not-null type. | ||
* | ||
* ``` | ||
* class ExampleViewModel(savedStateHandle: SavedStateHandle) { | ||
* // This code equals to below code: | ||
* // var foo: String | ||
* // get() = savedStateHandle["foo"]!! | ||
* // set(value) { savedStateHandle["foo"] = value } | ||
* // | ||
* // init { | ||
* // if (!savedStateHandle.contains("foo")) { | ||
* // savedStateHandle["foo"] = "init" | ||
* // } | ||
* // } | ||
* var foo: String by savedStateHandle.notNull("init") | ||
* } | ||
* ``` | ||
* | ||
* @param initialValue The initial value of this property. | ||
*/ | ||
public fun <T> SavedStateHandle.notNull(initialValue: T): NotNullPropertyDelegateProvider<T> { | ||
return NotNullPropertyDelegateProvider(savedStateHandle = this, initialValue) | ||
} | ||
|
||
public class NotNullPropertyDelegateProvider<T>( | ||
private val savedStateHandle: SavedStateHandle, | ||
private val initialValue: T | ||
) { | ||
public operator fun provideDelegate(self: Any?, property: KProperty<*>): NotNullPropertyDelegate<T> { | ||
val key = property.name | ||
if (!savedStateHandle.contains(key)) { | ||
savedStateHandle[key] = initialValue | ||
} | ||
return NotNullPropertyDelegate(savedStateHandle, key) | ||
} | ||
} | ||
|
||
public class NotNullPropertyDelegate<T>( | ||
private val savedStateHandle: SavedStateHandle, | ||
private val key: String | ||
) { | ||
public operator fun getValue(self: Any?, property: KProperty<*>): T { | ||
return savedStateHandle[key]!! | ||
} | ||
|
||
public operator fun setValue(self: Any?, property: KProperty<*>, value: T) { | ||
savedStateHandle[key] = value | ||
} | ||
} |
Oops, something went wrong.