Skip to content

Instantly share code, notes, and snippets.

@ZakTaccardi
Last active August 1, 2019 07:44
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ZakTaccardi/ca8bdbbc48d724f47d596072fb4b68d1 to your computer and use it in GitHub Desktop.
Save ZakTaccardi/ca8bdbbc48d724f47d596072fb4b68d1 to your computer and use it in GitHub Desktop.
A better way to launch activities. Companion code to https://medium.com/@ZakTaccardi/a-better-way-to-launch-activities-8a1045181b16
@file:Suppress("unused", "FunctionName", "IllegalIdentifier")
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
/**
* The best way to launch yourself an activity. Your implementation should enable the following api:
*
* ```kotlin
* YourActivityArgs(param1, param2)
+ .launch(activityContext);
* ```
*
* Your deserialization (from an intent) could look like:
*
* ```kotlin
* YourActivityArgs.of(intent)
* ```
*/
interface ActivityArgs {
/**
* @return returns an intent that can be used to launch this activity.
*/
fun intent(activity: Context): Intent
/**
* Launches the activity given your activity context.
*
* The default implementation uses the intent generated from [intent]
*/
fun launch(activity: Context) = activity.startActivity(intent(activity))
}
@SuppressLint("Registered")
class MediumProfileActivity : Activity() {
private val args by lazy {
MediumProfileActivityArgs.deserializeFrom(intent)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// easily reference` your activity's arguments!
args.name
args.shortBio
args.profilePhotoUrl
}
}
/**
* Arguments to launch [MediumProfileActivity]
*/
data class MediumProfileActivityArgs(
val name: String,
val shortBio: String,
val profilePhotoUrl: String
) : ActivityArgs {
override fun intent(activity: Context): Intent = Intent(
activity, MediumProfileActivity::class.java
).apply {
putExtra(NAME_KEY, name)
putExtra(SHORT_BIO_KEY, shortBio)
putExtra(PROFILE_PHOTO_URL_KEY, profilePhotoUrl)
}
companion object {
fun deserializeFrom(intent: Intent): MediumProfileActivityArgs {
return MediumProfileActivityArgs(
name = intent.getStringExtra(NAME_KEY),
shortBio = intent.getStringExtra(SHORT_BIO_KEY),
profilePhotoUrl = intent.getStringExtra(PROFILE_PHOTO_URL_KEY)
)
}
}
}
private const val NAME_KEY = "name_key"
private const val SHORT_BIO_KEY = "short_bio_key"
private const val PROFILE_PHOTO_URL_KEY = "profile_photo_url_key"
@SuppressLint("Registered")
class SomeOtherActivity : Activity() {
fun goToMediumProfile() {
val currentActivity = this
MediumProfileActivityArgs(
"Zak Taccardi",
"Eat. Sleep. Android.",
"www.profile.com/ZakTaccardi.png"
)
.launch(currentActivity)
}
}
@Test
fun `test args serialization and de-serialization`() {
val expectedArgs = MediumProfileActivityArgs(
"Zak Taccardi",
"Eat. Sleep. Android.",
"www.profile.com/ZakTaccardi.png"
)
// serialize args to intent
val serializedIntent = expectedArgs.intent(context)
// deserialize intent into args instance
val actualArgs = MediumProfileActivityArgs.deserializeFrom(serializedIntent)
// verify de-serialized args are equal to original args
Assertions.assertThat(actualArgs)
.isEqualTo(expectedArgs)
}
// the below serves to avoid red compilation errors above
annotation class Test
class Assertions {
companion object {
fun assertThat(actualArgs: MediumProfileActivityArgs) = AssertionHelper
object AssertionHelper {
fun isEqualTo(expected: MediumProfileActivityArgs) {}
}
}
}
@SuppressLint("StaticFieldLeak")
val context: Context = null!!
@nieldeokar
Copy link

Well written ! 👍

In case anyone looking for startActivityForResult :

fun launchActivityForResult(activity: Activity,requestCode : Int) = activity.startActivityForResult(intent(activity),requestCode)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment