GitXplorerGitXplorer
z

requireKTX

public
113 stars
3 forks
0 issues

Commits

List of commits on branch main.
Unverified
26eaa46f0d430bd1efbe3c73f64d9e669ba5b775

Update yarn lock file

zzsmb13 committed 4 months ago
Unverified
e4f3ea2a21957d65ffb0b562c39aaac1e88e7938

Update CI setup

zzsmb13 committed 4 months ago
Unverified
378c43487f8af66ab6619e6ecdbff06bbfafb666

Update dependency versions and publishing setup

zzsmb13 committed 4 months ago
Unverified
c41e0edcd34f7c095f0882ae15e4fe86d3d0e046

Fix versions in README

zzsmb13 committed 8 months ago
Unverified
4ffd43fc10de61de062bd167f83547a92cf09762

Fix publication runner, bump version to 2.0.0-alpha02

zzsmb13 committed 8 months ago
Unverified
2c797ace5b3336869d5a6189b99359e97291842d

Fix publish workflow

zzsmb13 committed 8 months ago

README

The README file for this repository.

requireKTX

requireKTX is a collection of small utility functions to make it easier to work with values that should always exist on Android and Kotlin Multiplatform, in the style of requireContext, requireArguments, and other similar Android SDK methods.

Types that requireKTX provides extensions for:

Why?

Take the example of grabbing a Bundle and reading a String ID from it that should always be there: the Bundle APIs give you a nullable result, which means you'll have to do some kind of null handling.

// Without requireKTX 😥
val id: String = argumentBundle.getString("user_id")!!

The exception potentially thrown by this code also won't be too helpful in tracking down the problem, as it won't tell you details such as whether the value was missing, or if it was the wrong type for the request.

Another problem with Bundles is accessing primitive values, as they're always returned as non-nullable, defaulting to 0 (or even worse, false for Booleans) if the key is not found or its associated value has the wrong type:

val bundle = Bundle()
bundle.putDouble("count", 123.0)

// These both pass 😱
assertEquals(0, bundle.getInt("count"))
assertEquals(0, bundle.getInt("score"))

This makes it difficult to know if what you received was a real 0 value, or if something silently went wrong.


Instead of using these methods, requireKTX provides extensions such as requireString, which you can use to require a value that must always be there:

// With requireKTX 🥳
val id: String = argumentBundle.requireString("user_id")
val count: Int = argumentBundle.requireInt("count")

These methods give you non-nullable return types. If the key isn't set or the value doesn't have the expected type, they throw meaningful exceptions based on the error that occurred. This is true for accessing primitive values as well.

getOrNull

requireKTX also includes getOrNull style methods for everything that it covers with require style methods,to make the nullable case more obvious and explicit. These match the conventions of the Kotlin Standard Library, and can make it clearer that null is returned if a value for a key couldn't be fetched.

val userId: String? = requireArguments().getStringOrNull("user_id")
val count: Int? = requireArguments().getIntOrNull("count")

Dependencies

requireKTX is published on Maven Central.

repositories {
    mavenCentral()
}

There are several artifacts you can import depending on which types you want to get extensions for - see the module descriptions below to learn more.

dependencies {
    // commonMain or Android
    implementation("co.zsmb:requirektx-bundle:2.0.0-alpha03")
    implementation("co.zsmb:requirektx-navigation:2.0.0-alpha03")

    // Android only
    implementation("co.zsmb:requirektx-intent:2.0.0-alpha03")
    implementation("co.zsmb:requirektx-work:2.0.0-alpha03")
}

Available modules and extensions

Bundle

The requirektx-bundle artifact works with the androidx.core.bundle.Bundle type, available on Android and other Kotlin Multiplatform targets from org.jetbrains.androidx.core:core-bundle.

Given a Bundle, you can require the following types of values:

// Primitives (examples)
bundle.requireBoolean()
bundle.requireByte()
bundle.requireChar()
bundle.requireDouble()
bundle.requireFloat()

// Reference types
bundle.requireString()
bundle.requireBundle()
bundle.requireCharSequence()
bundle.requireParcelable()
bundle.requireSerializable()

// Arrays (examples)
bundle.requireBooleanArray()
bundle.requireByteArray()
bundle.requireCharArray()
bundle.requireDoubleArray()
bundle.requireFloatArray()

... and many more!

NavBackStackEntry

The requirektx-navigation artifact works with the androidx.navigation.NavBackStackEntry type, available on Android and other Kotlin Multiplatform targets from org.jetbrains.androidx.navigation:navigation-runtime.

This is compatible with both the Jetpack Navigation component on Android (with or without Compose) and the Compose Multiplatform navigation library.

To get the bundle of arguments from an entry, use requireArguments:

val args: Bundle = navBackStackEntry.requireArguments()

Here's an example of using this with Compose Navigation, in combination with the Bundle extensions:

composable(
    "detail/{objectId}",
    arguments = listOf(navArgument("objectId") { type = NavType.IntType }),
) { backStackEntry ->
    val args = backStackEntry.requireArguments()
    val objectId = args.requireInt("objectId")
    // UI implementation
}

Intent

The requirektx-intent artifact works with the android.content.Intent type, available on Android only.

Given an Intent, you can require its extras Bundle (and then require values from it as seen above):

val extras: Bundle = intent.requireExtras()

Or you can require specific extras directly for various types of values:

// Primitives (examples)
intent.requireBooleanExtra()
intent.requireByteExtra()
intent.requireCharExtra()
intent.requireDoubleExtra()
intent.requireFloatExtra()

// Reference types
intent.requireStringExtra()
intent.requireBundleExtra()
intent.requireCharSequenceExtra()
intent.requireParcelableExtra()
intent.requireSerializableExtra()

// Arrays (examples)
intent.requireBooleanArrayExtra()
intent.requireByteArrayExtra()
intent.requireCharArrayExtra()
intent.requireDoubleArrayExtra()
intent.requireFloatArrayExtra()

... and many more!

WorkManager Data

The requirektx-work artifact provides extensions for the androidx.work.Data type, available on Android only.

Given a WorkManager Data object (such as inputData inside a worker), you can require the following types of values:

class SomeWorker : Worker() {
    override fun doWork(): Result {
        // Values
        inputData.requireBoolean()
        inputData.requireByte()
        inputData.requireDouble()
        inputData.requireFloat()
        inputData.requireInt()
        inputData.requireLong()
        inputData.requireString()

        // Arrays
        inputData.requireBooleanArray()
        inputData.requireByteArray()
        inputData.requireDoubleArray()
        inputData.requireFloatArray()
        inputData.requireIntArray()
        inputData.requireLongArray()
        inputData.requireStringArray()

        // ...
    }
}

License

Copyright 2021 Márton Braun

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.