A Bundle Creator for android Activity and Fragment. it can be used for creating an initial bundler or saving their instance.
Inspired by: fragmentargs
and with a lot of help from KotlinPoet and kotlinx-metadata
I'll put all the resource that I used for creating this module in LearningResource.md file
Step 1. Add the JitPack repository to your build file
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
...
}
}Step 2. Add kotlin-kapt to your app gradle plugin (app:build.gradle)
plugins {
...
id 'kotlin-kapt'
}Step 3. Add ArgumentBuilder dependencies to your app:build.gradle
implementation "com.github.moodi1999.ArgumentBuilder:argument-annotation:${lastVersion}"
kapt "com.github.moodi1999.ArgumentBuilder:argument-processor:${lastVersion}"Step 4. Add @ArgumentBuilderTarget to your Fragment or Activity
@ArgumentBuilderTarget
class MainActivity : AppCompatActivity() {
...
}Step 5. Add @Argument or @SaveInstance to your public mutable argument
options:
- custom key
- isRequired
@ArgumentBuilderTarget
class MainActivity : AppCompatActivity() {
@Argument
var stringArgument = ""
@Argument
var mapArgument: Map<Double, Float>? = null
...
}options:
- customKey
@ArgumentBuilderTarget
class SaveInstanceActivity : AppCompatActivity() {
@Argument
@SaveInstance
var stringArgument = ""
...
}Step 6. build your project.
ArgumentBuilder will generate a class like this for Arguments:
public class MainActivityCreator() {
private var _bundle: Bundle? = Bundle()
private val bundle: Bundle
get() = _bundle!!
public fun stringArgument(stringArgument: String): MainActivityCreator {
bundle.putString(stringArgument_arg_key, stringArgument)
return this
}
public fun mapArgument(mapArgument: Map<Double, Float>): MainActivityCreator {
bundle.putBundle(mapArgument_arg_key, Bundle().apply {
mapArgument.onEachIndexed { index, (mKey, mValue) ->
val key_key_1650951646 = """key$index"""
val value_key_1650951646 = """value$index"""
putDouble(key_key_1650951646, mKey)
putFloat(value_key_1650951646, mValue)
}
})
return this
}
/**
* @return copy of [bundle]
*/
public fun createBundle(): Bundle = Bundle(bundle).also { _bundle = null }
public companion object {
private const val stringArgument_arg_key: String = "stringArgument_arg_key"
private const val mapArgument_arg_key: String = "mapArgument_arg_key"
public fun initialize(activity: MainActivity): Unit {
val arguments = requireNotNull(activity.intent.extras) {
"No arguments set. Have you set up this activity with the @ArgumentBuilderTarget?"
}
if (arguments.containsKey(stringArgument_arg_key)) {
activity.stringArgument = requireNotNull(arguments.getString(stringArgument_arg_key))
}
if (arguments.containsKey(mapArgument_arg_key)) {
activity.mapArgument = requireNotNull(arguments.getBundle(mapArgument_arg_key)?.run {
val outMap392637485 = mutableMapOf<Double, Float>()
for (index392637485 in 0..(size() / 2)) {
val key_key_392637485 = """key$index392637485"""
val value_key_392637485 = """value$index392637485"""
outMap392637485[getDouble(key_key_392637485)!!] =
getFloat(value_key_392637485)!!
}
outMap392637485
})
}
}
}
}
or an object like this for SaveInstances:
/**
* saving Activity state for [SaveInstanceActivity]
*/
public object SaveInstanceActivitySaveInstanceBuilder {
private const val stringArgument_saveInstance_key: String = "stringArgument_saveInstance_key"
public fun saveInstanceState(SaveInstanceActivity: SaveInstanceActivity, outState: Bundle): Unit {
SaveInstanceActivity.apply {
outState.putString(stringArgument_saveInstance_key, stringArgument)
}
}
public fun restoreSavedInstance(Activity: SaveInstanceActivity, savedInstanceState: Bundle?):
Unit {
if (savedInstanceState == null) {
return
}
Activity.apply {
stringArgument = requireNotNull(savedInstanceState.getString(stringArgument_saveInstance_key))
}
}
}
BOCG = Bundle Operation Code Generator
ScalarsTypeBOCG(),
ReferencesTypeBOCG(),
BoxedArrayTypeBOCG(),
EnumTypeBOCG(),
NullableIntArrayTypeBOCG(),
StringAndCharSeqArrayTypeBOCG(),
PrimaryArrayListTypeBOCG(),
ParcelableArrayListTypeBOCG(),
CollectionParameterizedArgTypeBOCG(),
ParcelableSparseArrayTypeBOCG(),
ParcelableArrayTypeBOCG(),
ParcelableTypeBOCG(),
MapEntryIterateTypeBOCG(),
SerializableTypeBOCG(),These are code generators for supported types, you can check them in argument_processor inside operationGenerator
package. They contain a property that checks if the BOCG isApplicable to the given field.
Step 7. criticize or contribute
- it just supports kotlin types.
- you can have
CustomBundlerfor nonSupported types. example:object SomeLibClassCustomBundler : ArgumentBundler<SomeLibraryClass?> { override fun put(key: String?, value: SomeLibraryClass?, bundle: Bundle) { val someClassBundle = Bundle() requireNotNull(value).run { someClassBundle.putString("key", value.name) someClassBundle.putInt("key", value.age) } bundle.putBundle("classBundle", someClassBundle) } override fun <V : SomeLibraryClass?> get(key: String?, bundle: Bundle): V? { return bundle.getBundle("classBundle")?.let { // retrieve } as V? } } class SomeLibraryClass( val name: String, val age: Int, )
- "for now" it works, but it needs lots of renaming and documentation. => open for criticize and contribution
- it doesn't check all arguments and types constraints.
- there will be reconsideration for
Creatorclass API.
future goals will be in the issue section.