Skip to content
This repository has been archived by the owner on Nov 14, 2018. It is now read-only.

Property delegates for Activity extras #440

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/current.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
package androidx.core.activity {

public final class ActivityKt {
ctor public ActivityKt();
}

}

package androidx.core.animation {

public final class AnimatorKt {
Expand Down
1 change: 1 addition & 0 deletions src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
<application>
<activity android:name="androidx.core.TestActivity"/>
<activity android:name="androidx.core.TestPreferenceActivity"/>
<activity android:name="androidx.core.TextExtraActivity"/>
</application>
</manifest>
40 changes: 40 additions & 0 deletions src/androidTest/java/androidx/core/TextExtraActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.core

import android.app.Activity
import androidx.core.activity.extra

class TextExtraActivity : Activity() {

val stringExtra by extra<String>(EXTRA_STRING)
val intExtra by extra<Int>(EXTRA_INT)
val nullableIntExtra by extra<Int?>(EXTRA_NULLABLE_INT)
val intDefaultExtra by extra<Int>(EXTRA_INT_DEFAULT) { DEFAULT_INT }
val nullableIntDefaultExtra by extra<Int?>(EXTRA_NULLABLE_INT_DEFAULT) { DEFAULT_NULLABLE_INT }

companion object {
const val EXTRA_STRING = "string"
const val EXTRA_INT = "int"
const val EXTRA_NULLABLE_INT = "nullable_int"
const val EXTRA_INT_DEFAULT = "int_default"
const val EXTRA_NULLABLE_INT_DEFAULT = "nullable_int_default"

const val DEFAULT_INT: Int = 42
val DEFAULT_NULLABLE_INT: Int? = null
}
}
97 changes: 97 additions & 0 deletions src/androidTest/java/androidx/core/activity/ActivityTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.core.activity

import android.content.Intent
import android.os.Bundle
import android.support.test.rule.ActivityTestRule
import androidx.core.TextExtraActivity
import androidx.testutils.assertThrows
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Rule
import org.junit.Test

class ActivityTest {

@JvmField
@Rule
val rule = ActivityTestRule(TextExtraActivity::class.java, false, false)

@Test
fun get() {
val activity = launchExtraActivity {
putExtra(TextExtraActivity.EXTRA_STRING, "test")
putExtra(TextExtraActivity.EXTRA_INT, 1)
putExtra(TextExtraActivity.EXTRA_NULLABLE_INT, 2)
putExtra(TextExtraActivity.EXTRA_INT_DEFAULT, 3)
putExtra(TextExtraActivity.EXTRA_NULLABLE_INT_DEFAULT, 4)
}
assertEquals("test", activity.stringExtra)
assertEquals(1, activity.intExtra)
assertEquals(2, activity.nullableIntExtra)
assertEquals(3, activity.intDefaultExtra)
assertEquals(4, activity.nullableIntDefaultExtra)
}

@Test
fun getMissing() {
val activity = launchExtraActivity()
assertThrows<IllegalArgumentException> { activity.stringExtra }
assertThrows<IllegalArgumentException> { activity.intExtra }
assertNull(activity.nullableIntExtra)
assertEquals(TextExtraActivity.DEFAULT_INT, activity.intDefaultExtra)
assertEquals(TextExtraActivity.DEFAULT_NULLABLE_INT, activity.nullableIntDefaultExtra)
}

@Test
fun getNull() {
val activity = launchExtraActivity {
putExtra(TextExtraActivity.EXTRA_STRING, null as String?)
putExtra(TextExtraActivity.EXTRA_INT, null as Int?)
putExtra(TextExtraActivity.EXTRA_NULLABLE_INT, null as Int?)
putExtra(TextExtraActivity.EXTRA_INT_DEFAULT, null as Int?)
putExtra(TextExtraActivity.EXTRA_NULLABLE_INT_DEFAULT, null as Int?)
}
assertThrows<IllegalArgumentException> { activity.stringExtra }
assertThrows<IllegalArgumentException> { activity.intExtra }
assertNull(activity.nullableIntExtra)
assertEquals(TextExtraActivity.DEFAULT_INT, activity.intDefaultExtra)
assertEquals(TextExtraActivity.DEFAULT_NULLABLE_INT, activity.nullableIntDefaultExtra)
}

@Test
fun getWrongType() {
val activity = launchExtraActivity {
putExtra(TextExtraActivity.EXTRA_STRING, Bundle())
putExtra(TextExtraActivity.EXTRA_INT, Bundle())
putExtra(TextExtraActivity.EXTRA_NULLABLE_INT, Bundle())
putExtra(TextExtraActivity.EXTRA_INT_DEFAULT, Bundle())
putExtra(TextExtraActivity.EXTRA_NULLABLE_INT_DEFAULT, Bundle())
}
assertThrows<IllegalArgumentException> { activity.stringExtra }
assertThrows<IllegalArgumentException> { activity.intExtra }
assertThrows<IllegalArgumentException> { activity.nullableIntExtra }
assertEquals(TextExtraActivity.DEFAULT_INT, activity.intDefaultExtra)
assertEquals(TextExtraActivity.DEFAULT_NULLABLE_INT, activity.nullableIntDefaultExtra)
}

private fun launchExtraActivity(configure: Intent.() -> Unit = {}): TextExtraActivity {
val intent = Intent().apply(configure)
return rule.launchActivity(intent)
}
}
81 changes: 81 additions & 0 deletions src/main/java/androidx/core/activity/Activity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.core.activity

import android.app.Activity

/**
* Returns a [Lazy] instance that parses the receiver's input intent and extracts an extra from type
* [T] mapped by the input [key].
*
* The returned value can be used as a property delegate, for instance:
*
* ```kotlin
* class MyActivity : Activity() {
*
* private val name by extra<String>("name")
* }
* ```
*
* If such value can't be retrieved, an exception will be thrown. This will happen when:
*
* - There is an extra mapped by [key] and it can't be cast to [T]
* - There's no extra mapped by [key] and [T] is not a nullable type
*
* @param key The extra key
* @param T The extra type
* @return A [Lazy] that returns an intent extra
*/
inline fun <reified T> Activity.extra(key: String): Lazy<T> = lazy {
val value = intent.extras?.get(key)
if (value is T) {
value
} else {
throw IllegalArgumentException("Couldn't find extra with key \"$key\" from type " +
T::class.java.canonicalName)
}
}

/**
* Returns a [Lazy] instance that parses the receiver's input intent and extracts an extra from type
* [T] mapped by the input [key], returning the result of the [default] function in case the extra
* can't be extracted.
*
* The returned value can be used as a property delegate, for instance:
*
* ```kotlin
* class MyActivity : Activity() {
*
* private val name by extra("name") { "Default name" }
* }
* ```
*
* If such value can't be retrieved, the result from [default] will be returned. This will happen
* when:
*
* - There is an extra mapped by [key] and it can't be cast to [T]
* - There's no extra mapped by [key] and [T] is not a nullable type
*
* @param key The extra key
* @param default A function that returns the default value
* @param T The extra type
* @return A [Lazy] that returns an intent extra
*/
inline fun <reified T> Activity.extra(key: String, crossinline default: () -> T): Lazy<T> = lazy {
val value = intent.extras?.get(key)
if (value is T) value else default()
}