Ausgabe
Ich habe also eine ActorModel-Klasse, die eine Arraylist von MovieModel enthält. Ich habe versucht, es zu codieren und in einem Bündel an die nächste Aktivität zu senden. Allerdings heißt es:
kotlinx.serialization.json.internal.JsonDecodingException: Expected start of the object '{', but had 'EOF' instead at path: $
JSON input: kotlinx.serialization
Hier ist meine ActorModel-Klasse:
package com.sanjarbek.flixster2
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.Serializable
@Serializable
data class ActorModel(
val name: String,
val popularity: String,
val profile_path: String, ) {
var movieModelArrayList: ArrayList<MovieModel> = ArrayList<MovieModel>()
set(value) {field = value}
get() = field
fun mainMovie(): String {
val json = Json.encodeToString<ArrayList<MovieModel>>(movieModelArrayList)
return json
}
fun main(): String {
val json = Json.encodeToString(ActorModel(name, popularity, profile_path))
return json
}
}
gefolgt von der MovieModel-Klasse:
package com.sanjarbek.flixster2
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.Serializable
@Serializable
data class MovieModel (
private val original_title: String="",
private val poster_path: String="",
private val overview: String=""
) {
fun get_title(): String{
return original_title
}
fun get_image(): String{
return poster_path
}
fun get_description(): String{
return overview
}
}
Hier ist der Code, bei dem ich versucht habe, ihn mit Bundle zu senden:
holder.image.setOnClickListener {
val intent = Intent(context, ActorInfoActivity::class.java)
intent.putExtra("image", image_url)
intent.putExtra("name", model.name)
intent.putExtra("model", model.main())
context.startActivity(intent)
}
Und wo ich es empfange und entschlüssele:
val actor = Json.decodeFromString<ActorModel>("kotlinx.serialization")
val movies = Json.decodeFromString<ArrayList<MovieModel>>("kotlinx.serialization")
Log.d("TAG", "onCreate: $actor"
Log.d("TAG", "onCreate: $movies")
Lösung
Wenn Ihre Frage lautet, wie Sie die oben beschriebenen Objekte an eine andere Aktivität übergeben können, ist hierfür kein JSON-Objekt erforderlich. Android gibt uns die Tools, um dies sofort zu tun. Ich habe deine Klassen etwas umgeschrieben:
SchauspielerModell
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
data class ActorModel (
val name: String,
val popularity: String,
val profilePath: String,
var movieModelArrayList: MutableList<MovieModel> = mutableListOf()): Parcelable {
override fun toString(): String {
return "ActorModel(name=$name, popularity=$popularity, profilePath=$profilePath)\n" +
"movieModelArrayList=$movieModelArrayList"
}
}
MovieModel
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
data class MovieModel (
val original_title: String = "TestTitle",
val poster_path: String = "./Test",
val overview: String = "Test"
): Parcelable
I draw your attention to the @Parcelize
annotation and interface Parcelable
– this is the most important change to your code. Parcelable
process is much faster than Serializable
. One of the reasons for this is that we are being explicit about the serialization process instead of using reflection to infer it. In fact, we must manually implement the methods of the Parcelable
interface. But the creators of Kotlin took care of us and added the @Parcelize
annotation, which does all the dirty work for us. By default, it is not available, how to enable it is described in detail in the answer.
Sending data
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class TestActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val actor = ActorModel("Alex", "10", "./profiles")
actor.movieModelArrayList.add(MovieModel())
val intent = Intent(this, MainActivity::class.java)
val bundle = Bundle()
bundle.putParcelable("actor", actor)
intent.putExtras(bundle)
startActivity(intent)
}
}
Getting data
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val actor = intent.extras?.get("actor") as ActorModel
Log.i("Test", actor)
}
}
A small digression
In der
MovieModel
Klasse benötigen Sie keine Getter, da Sie die Felder bereits als val deklariert haben – sie sind nicht mehr änderbar und schreibgeschützt. Der private Modifikator macht also auch keinen Sinn. Es ist nicht mehr Java, entspannen Sie sich und genießen Sie Kotlin 🙂
Beantwortet von – Olexandr Kisurin
Antwort geprüft von – Mary Flores (FixError Volunteer)