Make class as Parcelable - java

I am currently trying to make one of my classes implement Parcelable but I can't do it properly. This is the class.
class T(val eyes:Int,val img:ImageButton){
var image = img
var value = eyes
var isPressed = false
}
Android Studio suggests that my constructor should look similar to this when implementing Parcelable, but I don't know how to use a parcel to initialize my ImageButton.
constructor(parcel: Parcel) : this(
parcel.readInt(),
//parcel.
) {
value = parcel.readInt()
isPressed = parcel.readByte() != 0.toByte()
}
Tried to use a parcel. any and cast it to an ImageButton without success, any suggestions on how to solve this? Thanks in advance.

If you want to make a class like this, you can create it in this way
class T(var eyes: Int, var img: ImageButton, var isPressed: Boolean = false)
ImageButton class doesn't implement the Parcelable interface, in this case, you cannot pass it into Parcel. It's not a good approach to put Views into Parcel, you can save their state into primitives or classes which implements Parcelable and restore it after that. For example, if you want to pass a text from EditText to another activity, you can put this text into Parcel as String, and restore it in the next Activity.

If you are using kotlin always use data class for model. and use #Parcelize annotation so you don't need to write extra boilerplate code. But in your case you can't Parcelize ImageButton it's not a class that implements Parcelable interface
In case you are searching about a normal way to implement, Just use like that:
#Parcelize
data class UserInformationData(
var userId : String? = null,
var firstName : String? = null,
var lastName : String? = null,
var email : String? = null,
var gender : String? = null,
var dateOfBirth : String? = null,
var phoneNumber : String? = null
):Parcelable

Related

How to create an object of proper type elegantly from the given input?

I get packets from the network that looks as follows in the following DTO form:
data class ContentElementField(
val text: String? = null,
val style: String? = null,
val imagePath: String? = null,
val caption: String? = null
)
The packet has the following invariant that specifies that either text and style or imagePath and caption are set together. One group excludes the other.
By following this invariant,
abstract class ContentElement
data class TextElement(val text: Text, val style: Style) : ContentElement()
data class ImageElement(val picturePath: Path, val caption: Text) : ContentElement()
either TextElement or ImageElement is created.
I abstain from writing a code as follows to implement this behavior:
if (isTextElementField(contentElementField)) createTextElement(contentElement.text, contentElement.style)
else if (isImageElementField(contentElementField)) createImageElement(contentElement.imagePath, contentElement.caption)
Because in the future, there will be more specific content elements to be added. This leads me to expand the branching above as more specific content elements are added.
I believe it can be implemented through polymorphism or double-dispatching through the visitor pattern.
What would you offer to solve this?

Adjust Textview according to variable in Kotlin

i am building an app in Android Studio using kotlin,
the app is a quiz app with a text in the end depending on the result.
I want to know, what is the smoothest way to move a value(i am guessing intent) from the first activity to the last, adjusting it on the way. And how do i use this value to adjust the string showed on the result activity?
I was thinking of creating strings for all results and name them result100, result200, result300 etc. then have a variable that changes according to the answers such as:
buttonParty.setOnClickListener{
desNumber = 100
val intent = Intent(this, ResultPageActivity::class.java)
intent.putExtra("EXTRA_DES", desNumber)
startActivity(intent)
}
retreive it with:
val desNumber = intent.getIntExtra("EXTRA_DES", 100)
than on the last activity:
resultText.setText = findViewById(R.string.result$desNumber)
But this doesnt seem to work unfortunately.
Thanks in advance for any help!
You can do this with something called ViewModel
So you would do something like this:
-On your parent activity (the first), create your ViewModel that will hold your data, and the functions that will alter (or retrieve) that data:
class GameActivity : AppCompatActivity() {
class GameData: ViewModel(){
//Creates the variables that hold the data, with a type that allows them to change over time,
//and to be "observed", but not be useful to this specific example, but this is what I usually use
private val _Result1 : MutableLiveData<String> by lazy {
MutableLiveData<String>().apply { value = "You got a Low Score" }
}
private val _Result2 : MutableLiveData<String> by lazy {
MutableLiveData<String>().apply { value = "You got a High Score" }
}
//Publishes the values of the strings without letting them being altered directly
val Result1 : LiveData<String>
get() = _Result1
val Result2 : LiveData<String>
get() = _Result2
}
}
-On the activity that you want to retrieve the data, do this:
//Declare the variable that will give access to the variables
private val dataModel : GameActivity.GameData by activityViewModels()
//Acess the variables
if(dataModel.Result1.value === "...")
While this answer shows how you can create a model to hold your data in one activity, and access in others, I think the way you are doing it (saving different messages to show) might be done better in a different way. Shouldn't you just save the "points" value in the data model, and use conditions to show the different messages?
You can save the points in this data model the same way it's done with the strings above, but with "Int" instead of "String" in the data types.

Map java Enum to Kotlin data class

I am making a call from service A which is in Kotlin to service B which is in Java. It return me an object which contains multiple fields. One of the fields returned in the Java object is an enum. In my kotlin code I have defined a DTO which maps the returned response to kotlin. I need to map this enum to a string value in kotlin.
DTO in Java:
public class PersonDTO
{
private Long id;
private String name;
private CountryCode countryCode;
}
The CountryCode is an enum.
Data class in Kotlin:
data class PersonDTO(
val id: Long? = null,
val name: String? = null,
val countryCode: String? = null //How to map the enum to string here..???
)
Any help would be appreciated.
Answer to the edited question: How to map a Java enum to a String?
you can call name() or toString() on an enum to get a String representation of it.
name() cannot be overwritten and always returns the textual representation of the value defined in the code, while toString() can be overwritten, so it might be depending on your use case what to use. Because of the fact that name() cannot be overwritten I prefer to always use name() wich can have less side effects or unexpected behavior when working with libraries which are not under your control.
Original Answer:
1 you don't have to do this. You can use the same Java class also in Kotlin code.
2 You could just reuse the enum, like in option 1) you can reuse the Java enum in Kotlin code:
data class PersonDTO(
val id: Long? = null,
val name: String? = null,
val countryCode: CountryCode
)
3 You can write a Kotlin enum with a mapping function to create the matching instance of the enum:
enum class KotlinCountryCode {
EXAMPLE;
fun fromJavaCountryCode(input: CountryCode): KotlinCountryCode? {
if (input.name() == EXAMPLE.name) {
return EXAMPLE
}
return null
}
}

Type mismatch, when passing arugment to Model Class

The problem is when I created the instance of my Model class and pass the non-nullable variable to the constructor, the compiler shows the error Type-mismatch.
I have fixed the type-mismatch error by making model class variable as nullable
But I couldn't understand the error shown by the compiler.
Model class
class SharedPreferenceEntry (val name:String, val dateOfBirth:Calendar, val email:String)
Helper class SharedPreferencesHelper, where I created an instance of Model class and return that instance from function
fun getPersonalInfo(): SharedPreferenceEntry { // Get data from the SharedPreferences.
val name = mSharedPreferences.getString(KEY_NAME, "")
val dobMillis =
mSharedPreferences.getLong(KEY_DOB, Calendar.getInstance().getTimeInMillis())
val dateOfBirth: Calendar = Calendar.getInstance()
dateOfBirth.setTimeInMillis(dobMillis)
val email = mSharedPreferences.getString(KEY_EMAIL, "")
// Create and fill a SharedPreferenceEntry model object.
return SharedPreferenceEntry(name, dateOfBirth, email)
}
As #sonnet commented, the use of mSharedPreferences.getString(...) will return null if the key is mapped to null. To ensure, the value of mSharedPreferences.getString(...) is non-null, change it to mSharedPreferences.getString(...) ?: "".

Kotlin data class implementing Java interface

I'm trying to introduce Kotlin into my current project. I've decided to begin with entities, which seem to map perfectly to data classes.
For example I have a data class:
data class Video(val id: Long, val ownerId: Long, val title: String, val description: String? = null,
val imgLink: String? = null, val created: Date? = null, val accessKey: String? = null,
val views: Long? = null, val comments: Long? = null, val videoLink: String? = null): Entity
Which implements Java interface:
public interface Entity {
Long getId();
}
But for some reason compiler doesn't understand that method is implemented already:
Class 'Video' must be declared abstract or implement abstract member public abstract fun getId(): kotlin.Long! defined in net.alfad.data.Entity
Do I have to use any additional keywords for id param? What does "!" mean in the signature?
The problem here is that Kotlin loads the Java class Entity first and it sees getId as a function, not as a getter of some property. A property getter in a Kotlin class cannot override a function, so the property id is not bound as an implementation of the getId function.
To workaround this, you should override the original function getId in your Kotlin class. Doing so will result in JVM signature clash between your new function and id's getter in the bytecode, so you should also prevent the compiler from generating the getter by making the property private:
data class Video(
private val id: Long,
...
): Entity {
override fun getId() = id
...
}
Note that this answer has been adapted from here: https://stackoverflow.com/a/32971284/288456
If this is your whole data class then you're not overriding getId(). I see that you have a property called id and Kotlin should generate a getter for that but that won't be marked with the override keyword which you need to indicate that you're overriding an abstract function.
-- EDIT --
Alexander beat me to it! His answer is better anyway! ;)

Categories

Resources