Store edittext into MutableList - android

I am trying to create a function that store 3 editext values into an object when a button is pressed. These objects are stored into an mutablelist, which will be returned and displayed in a recycleview.
fun getWish(): MutableList<Wish>{
val wishes : MutableList<Wish> = ArrayList()
add_button.setOnClickListener {
val name= name_input.getText().toString()
val price= price_input.getText().toString()
val url= url_input.getText().toString()
val wishTemp = Wish(name, price, url)
wishes.add(wishTemp)
print(wishTemp)
print(wishes)
}
return wishes
}
The issue is the list is not displaying in the recycleview. The recycle view adapter is not the issue because it was tested with a test list. Is my implementation not working?
Print function shows reference values not the actual string. However, the 'wishes' list is added to everytime the button is pressed.

Where are you displaying the new data in the RecyclerView? All you're doing here is creating a new list and adding some Wish objects to it. You need to add this stuff to your data set in the Adapter, and then call one of the notify* methods to tell it to update the display (like notifyDataSetChanged). You haven't shown where you're doing that, so there's no way for us to know if that implementation is working or not.
(You probably want to show your adapter code anyway, there's a difference between initialising it with some data, and updating it with some other data later)
You're getting references with print because, at a guess, Wish is a plain class and you haven't overridden the toString() method to make it print your strings nicely. If you can make it a data class that will give you a default implementation that prints the values of your constructor parameters.

Related

How to solve the problem of sending a mutable list to another activty listview or recycleview in andoid studio Kotlin

I just want to make a home screen with four cards, and when you click on one, it takes you to a different screen or activity with its details!
for example :
as shown below, I want to click on Villa card and it navigate to the screen that hold a list of villas
So the main idea is that I want to make one mutable list type of data class just like this:
data class details (var id:String, var image:Int, var title:String)
this form:
var data=mutableListOf( //my code )
please tell me how to make something just like this or send me link of tutorial !
I have tried a sendig the muteable list to another mutable list that hold the id of listview, and I don't know really what went wrong !
Create a data class named details with the properties that you want.
Create the objects you need and add them to a mutable list.
ie
val list = mutableListOf<Details>().apply {
add(Details(id = "1243", image = R.drawable.icon, title = "dog")}
you can add as many as you want.

list adapter with sections

I already have a list adapter that works properly. But I want to divide the object in the list into sections according to the date they were created. Something like this:
I found something called "sectioned recycler view" but couldn't find any documentation on that. I read all the related questions, but they all are either outdated or use a third-party library. What's the native way of implementing this feature?
There are a couple of approaches you could use. First the easy one:
make the header part of your item layout, but with GONE visibility by default
in onBindViewHolder, decide whether the header should be VISIBLE or GONE
The logic there depends on what you want, but it could be as simple as
val visible = position == 0 || items[position].date != items[position - 1].date
Basically you just need to work out what the condition is that would cause an item to be in a different "group" than the previous item, and then if it's met, show the header over that item.
The approach MarkL is talking about is more complex, but it's also more robust - by having separate Item and Header elements, you can treat them differently, and even do stuff like having the header collapse/show its children, select them all etc. You can do that with the other approach, but it requires more code since you're not really treating things as groups, it's more of a trick when it comes to displaying stuff.
Basically, ignoring the how for now, you need a list of headers and items. A sealed class is a good way to represent that:
sealed class ListElement {
data class Header(val date: Date) : ListElement()
data class Item(val itemData: YourItem) : ListElement()
}
I've made Item a wrapper class that holds your actual data object inside, since that's probably coming from elsewhere and you can't define it as part of this sealed class hierarchy - so sticking it inside one of the subclasses like this allows you to do that.
So now you can have a List<ListElement> containing Headers and Items in display order. Since you've mentioned creating the ViewHolders in a comment I won't explain all that, but basically when you're getting the item type for a position, you just need to check is Header or is Item and then handle it from there.
As for creating that list, there are lots of ways to do it - you could use groupBy to generate a Map of dates to lists of items, map each of those entries to a list of Header, Item, Item..., and flatten the whole thing into a single list:
items.map { Item(it) }
.groupBy { it.itemData.date }
.entries
.flatMap { (date, items) -> listOf(Header(date)) + items }
The advantage with a map like this is it's an actual grouped structure, so you can keep it around to generate flat lists for display - e.g. hiding a group's contents by only including the header in the list.
Or you could just build the list yourself, similar to the logic I mentioned in the first example - if the date has changed from the previous item, insert a Header first:
val list = mutableListOf<ListElement>().apply {
for (item in items) {
// add a header if the date changed - this handles the first header
// in an empty list too (where lastOrNull returns null, so the date is null)
val previousItemDate = (lastOrNull() as? Item)?.itemData?.date
if (previousItemDate != item.date) add(Header(item.date))
add(Item(item))
}
}
Or you could use fold. Don't forget to sort stuff!
You could create 2 types of view holders:
header which holds the date
data container which holds the other information.
And then create a list of objects which contain something like this:
listToBind = (header, data, data, header, data, data)
For your case, where header & info is the same object, you can do something like this:
take your object you receive from backend (example)
YourObject(val header: String, val info:InfoObject)
create 2 display objects, both inheriting from a type that your adapter accepts (say - AdapterDisplayEntity)
HeaderDisplayEntity(val header: String): AdapterDisplayEntity
InfoDisplayEntity(val info: InfoObject): AdapterDisplayEntity
now you can use your list that contains these items and submit to your adapter.
Use nested recycler view for this instead. You can check the example here.
Best solution for this scenario so far.
If you are using Jetpack Compose you can use the stickyHeader() as documented in the documentation

KOTLIN Why when i changed a List it is also accidentally changing another list

Hello i want to know why is my program changing selectedDataEdited List when i only changing editTransactionList ?
var editTransactionList: MutableList<Transaction>? = mutableListOf()
var selectedDataEdited: List<Transaction>? = listOf()
editTransactionList = listTest as MutableList<Transaction>
selectedDataEdited = listTest
var position = 0
println("edit $editTransactionList")
println("select $selectedDataEdited")
editTransactionList.get(position).apply {
amount = 2000
name = "K"
}
println("edit $editTransactionList")
println("select $selectedDataEdited")
editTransactionList.get(position).apply {
amount = 3000
name = "Z"
}
println("edit $editTransactionList")
println("select $selectedDataEdited")
the output is
edit [Transaction(amount=1000, name=T, test=1)]
select [Transaction(amount=1000, name=T, test=1)]
edit [Transaction(amount=2000, name=K, test=1)]
select [Transaction(amount=2000, name=K, test=1)]
edit [Transaction(amount=3000, name=Z, test=1)]
select [Transaction(amount=3000, name=Z, test=1)]
Variables are basically references. When you store an object in a variable you actually say "when using this variable please refer to this object". So if you "store" the same object into 2 different variables, each of them still refers to that same object. Getting the object using the first variable, making changes to it, and then accessing the second variable, will still get you that changed object.
You will need to copy the list to prevent the unwanted behavior. Keep in mind though that you would probably need a deep copy. Simply calling toList() on it for example only makes a shallow copy, which means that even though it will be a different list, the objects inside it will still refer to the original.
It's hard to tell what would work without knowing what Transaction looks like. If Transaction is a data class then selectedDataEdited = listTest.map { it.copy() } might work. See this example https://pl.kotl.in/Q_o8pYXVs
KOTLIN Why when i changed a List it is also accidentally changing another list
Because you don't have "another" list. You only have one list.
When you do selectedDataEdited = listTest, you assign a second reference to the same list. If you want two separate lists, you must create them, possibly by cloning the original list.
Instead of using as MutableList use toMutableList:
editTransactionList = listTest.toMutableList()
It will make a copy of your list instead of passing a reference to the same list.

How to avoid remove item from second list affects the original list in kotlin

What I am trying to do is keep an original list and two duplicated ones in which to perform operations. Say orginalList is a list of String and has 5 entries
duplicatedList = originalList
secondDuplicatedList = orignalList
duplicatedList.remove(0)
secondDuplicatedList.remove(1)
The values are removed from all three lists and at the end all three lists will have 3 entries.
I have seen a lot of similar questions, but I do not quite get it
Any help or suggestion would be great. thanks
duplicatedList = originalList
Using equal sign will make another pointer to the same location in memory (duplicatedList is not instantiated from scratch); so both duplicatedList & originalList points to the same list
Instead, you need to create a brand new list in memory with the same values of the original list.
You can use the Collection's extension function toMutableList() to do that:
duplicatedList = originalList.toMutableList()
secondDuplicatedList = originalList.toMutableList()
This extension function originally creates a new list:
public fun <T> Collection<T>.toMutableList(): MutableList<T> {
return ArrayList(this)
}
try
duplicatedList.addAll(originalList)

Best practice to access property in kotlin

I comes from Java background and working first time on Kotlin. For most of the people it will be basic question, but it may help people who start working first time on Kotlin and comes from Java background
So, let say I have listadapter and I want to set list of item in that. I have two options now.
1) create a private property which stores list of items and then create a setter for it, which set the list and call notifydatasetChanged()
2) create a property with set property function and then access like instance.property
Which will be better option in Kotlin out of above two options.
A property in Kotlin is nothing else then a getter and setter for a value. If you don't want to provide a getter, you have to use a fun setData(data: List).
Otherwise it's also possible to handle everything with the property
var data = listOf()
set(data: List) {
field = data
notifydatasetChanged()
}
But eventually it's even better to use an implementation with DiffUtil.

Categories

Resources