Comments (16)
One more thing:
To make activity start even easier we can consider adding buildIntent
extension function to Activity and Fragment with a different name just to start activities with optional initializer (the most often case):
Possible implementation:
inline fun <reified T : Activity> Activity.startActivity(
initializer: Intent.() -> Unit = {}
) {
val intent = Intent(this, T::class.java).apply { initializer() }
startActivity(intent)
}
Also, make sense to have startActivityForResult
extension
There is also an option to add extension function to Context, but this approach is not safe because a user can try to start activity from application context without FLAG_ACTIVITY_NEW_TASK
and will get runtime error
If it makes sense I can create a separate feature request.
from android-ktx.
inline fun <reified T : Activity> Context.startActivity(vararg args: Pair<String, Any>) {
val intent = Intent(this, T::class.java)
intent.putExtras(bundleOf(*args))
startActivity(intent)
}
from android-ktx.
@dovahkiin98 I don't like your proposal with vararg pair because of many reasons:
- You create one additional object on each argument + array on each call
- Not a big improvement comparing with standard api + initializer
startActivity<SomeActivity>(
"foo" to "bar",
"theAnswer" to 42
)
// vs
startActivity<SomeActivity> {
putExtra("foo", "bar")
putExtra("theAnswer", 42)
)
Also initilizer allow to write much more complicated code:
startActivity<SomeActivity> {
if (bar != null) putExtra("foo", bar)
putExtra("theAnswer", 42)
)
- Your solution is not type safe. You cannot put
Any
to bundle, only Parcelabel/Serializable/primitive types, so not sure howbundleOf
should work, but it cannot force user to pass only Parcelabel/Serializable types
from android-ktx.
Personal opinion, but while we use bundleOf("x" to y)
at work, I've never liked it. You can't be sure how exactly it builds the Bundle, and what getter you have to call to retrieve your object. 😞 The Intent.() -> Unit
builder is much cleaner.
from android-ktx.
Probably the cleanest would be if each Activity had to receive Parameters Object (With it's all attributes).
Bundle is too vague and unsafe.
from android-ktx.
Dupe of #154.
from android-ktx.
Actually I'm going to dupe that one onto this as this proposal is a lot closer to the prototype I have.
from android-ktx.
One of the main inconvenience when you need to pass Parcelable
to the new Acitivity
is that the name
for the "extra data" needs to be maintained somewhere as a String constant. And both the starter and the starting Activity
need to know that name
while what both sides only need is the "extra data"
My proposal to get ride of that String constant is using this:
inline fun <reified T : Activity> Context. newIntent(obj: Parcelable): Intent {
val intent = Intent(this, T::class.java)
val name = getExtraName(T::class.java)
intent.putExtra(name, obj)
return intent
}
// the name will be something like: com.your.package.YourCoolActivity.ExtraName
fun getExtraName(target: Class<out Activity>): String {
return "${target.canonicalName}.ExtraName"
}
And if you have startActivity
like this:
inline fun <reified T : Activity> Context.startActivity(obj: Parcelable) {
val intent = newIntent<T>(obj)
this.startActivity(intent)
}
Then the usage of that will be super simple:
startActivity<YourCoolActivity>(theParcelable)
To get the "extra data", you just need to create another extension function:
inline fun <reified T : Parcelable> Activity.getParameter(): T {
val name = getExtraName(this.javaClass)
val obj = intent.getParcelableExtra<T>(name)
return obj
}
This is how to use it from YourCoolActivity
:
val data = getParameter<TheParcelable>()
from android-ktx.
@gildor Why can't they both be added? each one offers a different implementation.
If you want to only add extras, you can use the one with vararg, and if you want to be more specific about the initialization, you can use the one with the lamba.
The method bundleOf is already in the API
fun bundleOf(vararg pairs: Pair<String, Any?>)
it checks if the type can be added to a bundle or not, and throws exceptions on any error.
Maybe something like this:
inline fun <reified T> Context.startActivity(vararg args: Pair<String, Any?>, init: Intent.() -> Unit = {}) {
val intent = Intent(this, T::class.java)
intent.putExtras(bundleOf(*args))
intent.apply(init)
startActivity(intent)
}
startActivity<MainActivity>("Number" to 1) {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
from android-ktx.
Here's what I've been using for starting Activities:
inline fun <reified A : Activity> Context.start(configIntent: Intent.() -> Unit = {}) {
startActivity(Intent(this, A::class.java).apply(configIntent))
}
inline fun Context.startActivity(action: String, configIntent: Intent.() -> Unit = {}) {
startActivity(Intent(action).apply(configIntent))
}
It is used like so:
start<AboutActivity>()
startActivity(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) {
data = Uri.fromParts("package", packageName, null)
}
I used start
over startActivity
for the first one because "Activity" is already present in the name of any Activity
who's naming convention follows Android recommendations.
from android-ktx.
Lots of good ideas in this thread. A use case to keep in mind while designing this is Intents used by testing, e.g. the example on this page: https://developer.android.com/reference/android/support/test/espresso/intent/Intents.html
from android-ktx.
Personally I would love to see intentFor
combining both ideas from startActivity
and bundleOf
, like Anko has:
inline fun <reified T: Any> Context.intentFor(vararg params: Pair<String, Any?>): Intent {
return Intent(context, T::class.java).apply { putExtras(bundleOf(*params)) }
}
from android-ktx.
@Ioane5 You're actually correct, you can use a @Parcelize data class
from android-ktx.
@Ioane5 I wrote a small library for typesafe Bundle
s, without any annotation processing, just plain Kotlin.
Here's an example: https://github.com/LouisCAD/Splitties/tree/72a7faef07ae8ad8918c5c5f4d1f9c0ff3aad0f3/intents/README.md#example
I doubt this would be integrated into Android KTX because it's a bit more than just extensions, but it is an alternative to SafeArgs (currently used for Navigation Architecture Components) from AndroidX, that is IMHO easier to setup, lighter and more versatile (works for Activities, Fragments, Services, BroadcastReceivers, saved instance state, and anything else that uses a Bundle
if you look at the fragmentargs and bundle modules).
from android-ktx.
@LouisCAD I forgot about SafeArgs at all.
I do like your approach, and clearly It's better than plain bundle, since you set parameter without string key.
But as I see, you cannot enforce parameters by using
start(DemoActivity) { intentSpec, extrasSpec ->
extrasSpec.showGreetingToast = isUserPolite // <-- clumsy me forgot this param
extrasSpec.optionalExtra = intentSpec.someText
}
What if user does not specify required parameter showGreetingToast
?
Will there be any compile error? I think no.
With SafeArgs
I hope compile time error is generated.
from android-ktx.
@Ioane5 This currently results into a runtime error, but in case of Fragments, it could be catched earlier with Android lint as required arguments are the ones delegated by arg()
(and not argOrNull
, argOrElse
or argOrDefault
). An annotation to mark BundleSpec
properties as required could make up for it for non Fragment
usages so lint can detect programmer errors there too. I currently have no experience with lint though, but you are into it, open an issue about it!
BTW, thanks to autocomplete on extrasSpec
in the example you showed, discovery is improved, which makes you much less likely to forget an intent extra, so I don't think it's so important.
from android-ktx.
Related Issues (20)
- Convenience DSL for Media Controller Callback event handling
- androidx.preference.PreferenceFragment not derived from androidx.fragment.app.Fragment HOT 2
- Manifest merger failed HOT 5
- Release of 1.0.0-alpha3 out of sync with this repo HOT 4
- Extension property of bitmap from ImageView HOT 1
- error: resource android:attr/fontVariationSettings not found. HOT 1
- ImageDecoder source and test issues HOT 7
- inline extension properties can't be used in SAM lambda functions due to compiler bug HOT 1
- Add popular libraries extensions in new module HOT 1
- AAPT2 Error HOT 1
- View.post with with this view as a parameter HOT 2
- Resources.Theme.resolveAttribute extension
- Improve View.doOnPreDraw(...) HOT 1
- Features suggestions: Live data transformation HOT 1
- Offer: AsyncTask replacement
- Can't use getString(String) : String HOT 2
- androidx.core.os.BundleKt.bundleOf: Imports for API 21 classes break on older devices HOT 2
- gradle error HOT 3
- Add support for manipulating a color as HSV HOT 1
- Hi everyone!
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from android-ktx.