I have 2 activities. And I need pass a lot of variables from one activity to another activity:
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra(ACCOUNT1, accoun1)
intent.putExtra(ACCOUNT2, accoun2)
intent.putExtra(ACCOUNT3, accoun3)
intent.putExtra(ACCOUNT4, accoun4)
intent.putExtra(ACCOUNT5, accoun5)
intent.putExtra(ACCOUNT6, accoun6)
intent.putExtra(ACCOUNT7, accoun7)
intent.putExtra(ACCOUNT8, accoun8)
intent.putExtra(ACCOUNT9, accoun9)
and so on. How can I make this transfer easier? Maybe is some other ways to pass multiply values from one activity to another activity?
I recently had a similar case.
How I solved:
I created an entity that kept all the information for me, that way, I just passed an object between activities, but I had everything I needed inside that object.
Hope this can help.
There is a bundleOf function in the Jetpack core-ktx library that works like mapOf.
val intent = Intent(this, SecondActivity::class.java)
val extras = bundleOf(
ACCOUNT1 to accoun1,
ACCOUNT2 to accoun2,
ACCOUNT3 to accoun3,
// etc.
)
intent.putExtras(extras)
But that doesn't save much code compared to just using apply unless you use the same bundle of extras in multiple places in your code:
val intent = Intent(this, SecondActivity::class.java).apply {
putExtra(ACCOUNT1, accoun1)
putExtra(ACCOUNT2, accoun2)
putExtra(ACCOUNT3, accoun3)
//...
}
You could make a parcelable data class that stores all your values and pass that instead. See instructions here for creating the class easily: https://developer.android.com/kotlin/parcelize
#Parcelize
data class AccountInfo(
val account1: String,
val account2: String,
val account3: String,
//...
): Parcelable
Then you can put this into your bundles, and you don't have to create a bunch of the same kinds of variables in both activities, because all the variables are inside one class.
val intent = Intent(this, SecondActivity::class.java).apply {
putExtra(ACCOUNT_INFO, myAccountInfoInstance)
}
if all of your variables has the same type you can add all to list and pass the list to second activity/fragment.
Related
So for one of my personal projects I want to pass an arraylist of ZipEntry objects from one activity to another but I am unable to do so. I have tried the following things:
Creating Bundle() and passing that bundle using putExtra()
Passing ArrayList directly using putExta()
Creating bundle & passing it using putExtra():
Implementation:
// Add data to intent and launch install activity
val newActIntent = Intent(this, InstallActivity::class.java)
val data = Bundle()
data.putSerializable("x", languageListAdapter.selectedItems)
newActIntent.putExtra("z", data)
this.startActivity(newActIntent)
Error:
java.lang.IllegalArgumentException: Parcel: unknown type for value split_config.en.apk
Passing ArrayList<> directly using putExtra()
Implementation:
val newActIntent = Intent(this, InstallActivity::class.java)
newActIntent.putExtra("x", languageListAdapter.selectedItems)
this.startActivity(newActIntent)
Error:
java.lang.IllegalArgumentException: Parcel: unknown type for value split_config.en.apk
Note: ZipEntry object is java.util.zip.ZipEntry
In order to send an ArrayList<ZipEntry> from one Activity to another you need to make sure that your ZipEntry object is serializable, you can do it by implementing Serializable interface.
You can also use Parcelable as an alternative of Serializable.
If you use Serializable you use getSerializableExtra and if it's Parcelable you use getParcelableArrayListExtra
#Parcelize
data class ZipEntry : Parcelable
Fixed this issue thanks to the comment from #wambada
Implementation:
Created a singleton object to store the ArrayLists
object ZipEntrySingleton {
var aList: ArrayList<ZipEntry>? = null
var lList: ArrayList<ZipEntry>? = null
}
Created the singleton object in activity 1 and passed the data to it.
// Add data to intent and launch install activity
val newActIntent = Intent(this, InstallActivity::class.java)
val x = ZipEntrySingleton
x.aList = xListAdapter.selectedItems
x.lList = yListAdapter.selectedItems
this.startActivity(newActIntent)
Retrieved the data in the new activity by using:
ZipEntrySingleton.aList
I'm learning the Activity Results API that replace the onActivityResult. I understand the concept and basic usage, but not sure what's the proper way to setup an intent that takes multiple input extras.
For example, I want to put two Boolean flags and one String to the intent, in the old way, I could do
Val intent = Intent(this, AnotherActivity::java.class)
intent.putExtra(key1, false)
intent.putExtra(key2, true)
intent.putExtra(key3, someString)
But how do I do this in createIntent method? And what would the input type for this custom ActivityResultContract?
One way I can see is using Intent as input type, like class CustomActivityContract : ActivityResultContract<Intent, Unit>(). But that doesn't feel right to me.
Any suggestion is appreciated!
You don't call createIntent() directly. Instead, pass your intent to the ActivityResultLauncher.launch() method.
val launcher = registerForActivityResult(StartActivityForResult()) { result ->
// handle result
}
launcher.launch(
Intent(this, AnotherActivity::class.java)
.putExtra(key1, false)
.putExtra(key2, true)
.putExtra(key3, someString)
)
I followed this guide (How to run a certain activity in Android Studio?) to launch another activity aside from my main.
I have a GetUser.xml and ShowUser.xml layouts.
In GetUser.xml, user can enter their name and age.
I have a user class with constructor that takes in name and age inside GetUser.kt. I initialize User object with the values : name, age I got from the input fields in GetUser.
Now when I run the other activity ShowUser, I wish to access this object so I can get the values and display it in ShowUser.xml
My question is how do I access this object from the GetUser.kt and use it in ShowUser.kt ?
As far as I understand, you are looking for extra.
When starting one Activity from another, you can pass data via extra.
Let's say you have a class Person with String name and int age.
There are 2 simple ways to to this.
1. Send data separately
Because Person is a simple class that consists of 2 member fields, we can pass each data separately and combine into Person in started Activity.
We need Intent to do this.
val p = Person(name, age) // Person data
val intent = Intent(this, NewActivity::class.java)
intent.putExtra('name', p.name)
intent.putExtra('age', p.age)
startActivity(intent)
On started NewActivity's onCreate(), you can receive this data and make an object out of it.
val name = intent.getStringExtra('name')
val age = intent.getIntExtra('age')
val combinedPersonData = Person(name, age)
2. Send whole instance
If the class you are trying to send is too big to use method 1, you can try sending it as itself.
To do this, you need to implement Serializable or Parcelable to your class.
class Person(val name: String, val age: Int): Serializable { ... }
Make sure all of the members in the class are also Serializable or are primitive types.
With this, you can send the person object as serializable object.
val p = Person(name, age) // Person data
val intent = Intent(this, NewActivity::class.java)
intent.putExtra('person', p)
startActivity(intent)
In the receiver's onCreate(),
val p = intent.getSerializableExtra('person') as Person
will receive the while Person data.
I'm creating an Intent like so:
public void showThings(ArrayList<Thing> things) {
Intent intent = new Intent(this, ThingActivity.class);
intent.putExtra(THINGS, things);
startActivity(intent);
}
Then in the ThingActivity I want to get the ArrayList<Thing>
class ThingActivity {
var things: ArrayList<Thing>? = null
override fun onCreate(savedInstanceState: Bundle?) {
things = intent.extras.getSerializable(OtherActivity.THINGS) as? ArrayList<Thing>
}
Unfortunately, I can't seem to figure out how to cast to the appropriate type without triggering an "unchecked cast" warning. Is there a way to gracefully set to null if (somehow unexpectedly) the cast fails?
Appending ?: return null does not seem to work as I've seen suggested elsewhere
The unchecked cast warning is happening due to the way Java generics work at runtime. Because of type erasure, at runtime, the type of the list is just List, and not List<Thing>. That means that the cast is considered unsafe, even though it's quite possible for a human to look at the code and see that there's no problem.
While I agree with you that suppressing the warning isn't ideal, in this case I think it's fine.
The best solution, though, would be to implement the Parcelable interface on Thing. That way, when you want to pass a List<Thing> through an intent, you could write:
intent.putParcelableArrayListExtra(THINGS, things)
And when you want to read it back out:
things = intent.extras.getParcelableArrayListExtra(OtherActivity.THINGS)
Neither of these will cause a compiler warning.
As an alternative to Ben P's answer, you could use Gson.
Assuming that Things is simply a data class (holds a bunch of variables), this will work perfectly (this is also required by Ben P's answer).
Here's a way to implement it:
public void showThings(ArrayList<Thing> things) {
String json = new Gson().toJson(things);
Intent intent = new Intent(this, ThingActivity.class);
intent.putExtra(THINGS, json);
startActivity(intent);
}
Then you can get the ArrayList like this:
String json = intent.getStringExtra(THINGS);
TypeToken<ArrayList<Things>> token = new TypeToken<ArrayList<Things>>() {};
ArrayList<Things> things = new Gson().fromJson(json, token.getType());
Activity one:
val intent = Intent(this, SecondActivity::class.java)
val arrayGuide = ArrayList<Guide>()
intent.putParcelableArrayListExtra("arrayInfo",arrayGuide)
startActivity(intent)
Activity two:
if(intent != null){
val arrayList =
this.intent.getParcelableArrayListExtra<Guide>("arrayInfo")
}
fun kullaniciOlustur2(view: View){
val intent = Intent(applicationContext,KullaniciOlustur2::class.java)
intent.putExtra("input",makeUsername.text.toString())
intent.putExtra("input2",makeUserphone.text.toString())
startActivity(intent)
}
Mainactivity2 starts here..before this, I was using
val intent = intent
val received: String = intent.getStringExtra("input")
makeUsername.text = received
But this method doesn't work anymore.
I tried using getIntent() but couldn't get anything
val intent = getIntent()
Try this code
Activity 1
val intent = Intent(FirstActivity.this,SecondActivity::class.java) //not application context
intent.putExtra("input",makeUsername.text.toString())
intent.putExtra("input2",makeUserphone.text.toString())
startActivity(intent)
Activity 2
inside onCreate() method use
val stringOne = getIntent().getStringExtra("input")
Or more cleaner way is
val extras = getIntent().getExtras()
if (null != extras) {
val value = extras.getString("input")
//The key argument here must match that used in the other activity
}
and please check similar answers in Java, you may be able to get the Idea here already told in another answer.
I also Use Anko to remove this kind of boilerplate code
I recommend using Kotlin Anko, there are plenty of methods that will help you to remove this boilerplate code
check Anko Intents here
Use Below Code:
The Code is same as Java .Just difference is kotlin do not have
1. No semicolon at the end.
2. to call another activity kotlin use ::
ex.KotlinActivity::class.java
startActivity(Intent(this, KotlinActivity::class.java).putExtra("DataTrasfer", ""))
To Get Value:
intent.getStringExtra("DataTrasfer")