I want to update my object in Room by id, but it doesn't work.
Here is my DAO class
#Query("UPDATE greeting SET id =:id")
abstract fun updateGreetingByID(id: String)
Here is my DBHelper
fun updateGreetingByID(id: String) {
Thread { dataBase.greetingDao().updateGreetingByID(id) }.start()
}
My model
#Entity(tableName = "greeting")
class GreetingModel(
id: String? = "",
greetingCategory: String = "",
isFavourite: Boolean = false,
position: Int = 0
) : Parcelable {
#PrimaryKey(autoGenerate = true)
var _id: Int = 0
#ColumnInfo(name = "id")
var id: String? = null
#ColumnInfo(name = "greetingCategory")
var greetingCategory: String? = null
#ColumnInfo(name = "isFavourite")
var isFavourite: Boolean? = null
#ColumnInfo(name = "imageId")
var imageId: ByteArray? = null
#ColumnInfo(name = "position")
var position: Int = 0
#ColumnInfo(name = "saved")
var saved: Int = 0
constructor(parcel: Parcel) : this(
) {
_id = parcel.readInt()
id = parcel.readString()
greetingCategory = parcel.readString()
isFavourite = parcel.readValue(Boolean::class.java.classLoader) as? Boolean
imageId = parcel.createByteArray()
position = parcel.readInt()
saved = parcel.readInt()
}
init {
this.id = id
this.greetingCategory = greetingCategory
if (position != null) {
this.position = position
}
this.isFavourite = isFavourite
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(_id)
parcel.writeString(id)
parcel.writeString(greetingCategory)
parcel.writeValue(isFavourite)
parcel.writeByteArray(imageId)
parcel.writeInt(position)
parcel.writeInt(saved)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<GreetingModel> {
override fun createFromParcel(parcel: Parcel): GreetingModel {
return GreetingModel(parcel)
}
override fun newArray(size: Int): Array<GreetingModel?> {
return arrayOfNulls(size)
}
}
}
Where id is val id = UUID.randomUUID().toString()
I want to update object when user click to favourite button
val greetingModel = GreetingModel()
greetingModel.isFavourite = true
greetingModel.greetingCategory = " "
greetingModel.position = postImage
greetingModel.id?.let { helper.updateGreetingByID(greetingModel.id!!) }
My update method doesn't work. Hope, you will help!
Your issue is that you are trying to update according to a newly constructed Greeting that has the id as whatever value the id is set to when the Greeting is constructed using the default (no parameters constructor).
The fix is to retrieve the specific id of the Greeting that was clicked and set the id to that value before doing the update.
Related
i am trying to create a video player app using kotlin , First of all I got the videos files by using MediaStore , than store this in ArrayList so far it's been perfect but When I made a folder list of videos, I tried to find out the size of those folders and how many video files there are in those folders, but I failed. like this (Image)
Check this image for more clear
This is my data class code (VideoItem.Kt)
import android.net.Uri
data class VideoItem(
val id: String,
val title: String,
val duration: Long = 0,
val folderName: String,
val size: String,
val path: String,
val dateAdded: String,
val artUri: Uri
)
data class FolderItem(
val id: String,
val folderName: String,
val folderSize: Long
)
This is my MainActivity Code To get Allvideos Using MediaStore
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
companion object {
lateinit var videoList: ArrayList<VideoItem>
lateinit var folderList: ArrayList<FolderItem>
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
folderList = ArrayList()
videoList = getAllVideos()
setFragment(VideoviewFragment())
}
private fun setFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.FrameLayout, fragment)
transaction.disallowAddToBackStack()
transaction.commit()
}
#SuppressLint("Recycle", "Range")
private fun getAllVideos(): ArrayList<VideoItem> {
val tempList = ArrayList<VideoItem>()
val tempFolderList = ArrayList<String>()
val projection = arrayOf(
MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media._ID,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DATE_ADDED,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.BUCKET_ID
)
val cursor = this.contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
null,
null,
MediaStore.Video.Media.DATE_ADDED + " DESC"
)
if (cursor != null)
if (cursor.moveToNext())
do {
val titleC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE))
val idC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media._ID))
val folderNameC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME))
val folderIdC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID))
val sizeC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
val pathC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA))
val dateAddedC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATE_ADDED))
val durationC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DURATION))
.toLong()
try {
val file = File(pathC)
val artUriC = Uri.fromFile(file)
val video = VideoItem(
title = titleC,
id = idC,
folderName = folderNameC,
size = sizeC,
path = pathC,
duration = durationC,
dateAdded = dateAddedC,
artUri = artUriC
)
if (file.exists()) tempList.add(video)
//for adding Folders
if (!tempFolderList.contains(folderNameC)) {
tempFolderList.add(folderNameC)
val folderSizeC = getFileLength(pathC)
folderList.add(
FolderItem(
id = folderIdC,
folderName = folderNameC,
folderSize = folderSizeC
)
)
}
} catch (_: Exception) {
}
} while (cursor.moveToNext())
cursor?.close()
return tempList
}
private fun getFileLength(path: String?): Long {
return if (!isExistFile(path)) 0 else File(path.toString()).length()
}
private fun isExistFile(path: String?): Boolean {
val file = File(path.toString())
return file.exists()
}
}
This is my RecyclerviwAdapter Code(FolderAdapter.kt)
class FoldersAdapter(private val context: Context, private var foldersList: ArrayList<FolderItem>) :
RecyclerView.Adapter<FoldersAdapter.MyHolder>() {
class MyHolder(binding: FolderItemBinding) : RecyclerView.ViewHolder(binding.root) {
val folderName = binding.folderName
val noofFiles = binding.nooffiles
val folderSize = binding.foldersize
val root = binding.root
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
return MyHolder(FolderItemBinding.inflate(LayoutInflater.from(context), parent, false))
}
override fun onBindViewHolder(holder: MyHolder, position: Int) {
holder.folderName.text = foldersList[position].folderName
val size: Long = foldersList[position].folderSize
holder.folderSize.text = android.text.format.Formatter.formatFileSize(context, (size))
holder.root.setOnClickListener {
val intent = Intent(context, FolderVideosActivity::class.java)
intent.putExtra("position", position)
ContextCompat.startActivity(context, intent, null)
}
}
override fun getItemCount(): Int {
return foldersList.size
}
}
This is my all codes now please check out all code and suggest the best.
Thank you
Use this function for size
private fun getFolderSize(f: File): Long {
var size: Long = 0
if (f.isDirectory) {
for (file in f.listFiles()!!) {
size += getFolderSize(file)
}
} else {
size = f.length()
}
return size
}
And Count number of files Use this
val length = File("/path/to/folder").listFiles()?.size
I am using a custom adapter to display a list of contacts on AutoTextComplete but when I try to run it I get the error "kotlin.Unit cannot be cast to java.util.List" for
mContact = filterResults.values **as List<Contact>**
Contact is a Serializable object and is how i am retrieving contact names as objects in the List - code is below... I have tried looking for a solution elsewhere, but have not been able to resolve... if you can redirect or solution or guide will be amazing thanks
private var invoice: Invoice? = null
private lateinit var contact: Contact
private var invoiceItems: List<InvoiceItems>? = null
private lateinit var contactSelect: ArrayList<Contact>
private lateinit var dueDate: Calendar
private val calendar = Calendar.getInstance()
private var total = 0
private var subTotal = 0
private var taxrate = 0
private var invoiceType: String = ""
private var invoiceUpdt: InvoiceItems? = null
private var j: String? = null
private var clientLkey: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_edit_invoice)
val toolbar: Toolbar = findViewById(R.id.toolbar_editinv)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowHomeEnabled(true)
val invoiceClient = findViewById<AutoCompleteTextView>(R.id.invoiceClient)
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
dueDate = Calendar.getInstance()
//getting values from intent
invoice = intent.getSerializableExtra("invoice") as? Invoice
invoiceItems = intent.getSerializableExtra("invoiceItem") as? List<InvoiceItems>
invoiceUpdt = intent.getSerializableExtra("invoiceItemUpdt") as? InvoiceItems
j = intent.getStringExtra("i")
if (invoice == null){
invoiceType = "new"
supportActionBar?.title = "Add Invoice"
addinvoiceItem()
} else {
editInvoice()
}
//Setup Due date for the invoice
invoiceDueDt.setOnClickListener {
showCalendar()
}
//Auto complete based on database for selecting the client
val clientContact: List<Contact> = ArrayList<Contact>()
val adapter = ClientSelectAdapter(this, R.layout.userlatomcontacts, clientContact)
invoiceClient.setAdapter(adapter)
invoiceClient.threshold = 2
invoiceClient.setOnItemClickListener { parent, _, position, id ->
val selectedClient = parent.adapter.getItem(position) as Contact?
invoiceClient.setText(selectedClient?.name)
clientLkey = selectedClient?.lookupKey
}
}
inner class ClientSelectAdapter(
context: Context,
#LayoutRes private val layoutResource: Int,
private var allContacts: List<Contact>
):
ArrayAdapter<Contact>(context, layoutResource, allContacts),
Filterable {private var mContact: List<Contact> = allContacts
override fun getCount(): Int {
return mContact.size
}
override fun getItem(p0: Int): Contact {
return mContact[p0]
}
override fun getItemId(p0: Int): Long {
// Or just return p0
return mContact[p0].id.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var view = convertView
if (view == null) {
view = LayoutInflater.from(parent.context)
.inflate(layoutResource, parent, false)
}
val invoiceClient = view!!.findViewById<View>(R.id.invoiceClient) as TextView
invoiceClient.text = mContact[position].name
val clientProfile = view.findViewById<View>(R.id.profile_image) as ShapeableImageView
Picasso.get().load(mContact[position].photoUri)
.placeholder(R.drawable.ic_baseline_whatshot_24).fit().centerCrop()
.into(clientProfile)
return view
}
override fun getFilter(): Filter {
return object : Filter() {
override fun publishResults(
charSequence: CharSequence?,
filterResults: FilterResults
) {
**mContact = filterResults.values as List<Contact>**
notifyDataSetChanged()
}
override fun performFiltering(charSequence: CharSequence?): FilterResults {
val queryString = charSequence?.toString()?.toLowerCase(Locale.ROOT)
val results = FilterResults()
results.values = if (queryString == null || queryString.isEmpty())
allContacts
else {
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
}
return results
}
}
}
}
According to kotlin documentations Branches of if branches can be blocks. In this case, the last expression is the value of a block
So, in your case, when code enters the else block, the last expression is assignment, and assignments return Unit in kotlin. You may check this situation with this simple example:
var temp = 0
var result: Int = if (temp > 0) {
5
} else {
temp = 5
}
You would see the ide error at temp = 5 since it returns Unit whereas result expects Int.
To sum up, you just need to change your else block as follows:
else {
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
allContacts
}
I wish to use an boolean array (with specific size) in Room DB with constructor.
How I initialize it and how to use it?
#Entity
data class RoleEntity(
#PrimaryKey(autoGenerate = true) var id: Long? = null,
#ColumnInfo(name = "title") var title: String?,
#ColumnInfo(name = "startTime") var startTime: Long?,
#ColumnInfo(name = "endTime") var endTime: Long?,
#ColumnInfo(name = "recurrence") var recurrence: BooleanArray,
#ColumnInfo(name = "priority") var priority: Int?
): Serializable {
constructor() : this(title = "", startTime = 0, endTime = 0, recurrence = ??, priority = 0)
}
For such attributes, it is necessary to use converters, and in your case, I will give my example, you will have it there by analogy.#Convert(converter = ListJsonConverter::class) var list: List<Map<String, Any>>,
Also the converter itself
#Converter(autoApply = true)
class ListJsonConverter : AttributeConverter<List<Map<String, Any>>, String> {
private val objectMapper = ObjectMapper()
override fun convertToDatabaseColumn(attribute: List<Map<String, Any>>): String {
return objectMapper.writeValueAsString(attribute)
}
override fun convertToEntityAttribute(dbData: String?): List<Map<String, Any>> {
try {
return dbData?.let { objectMapper.readValue<List<Map<String, Any>>>(it) } ?: emptyList()
} catch (e: Exception){
return emptyList()
}
}
}
Here it is well written about them.
How can I stop creating a quoteData variable every time in my view model?
This solution is working, but the amount of repetitive code is terrifying
class QuoteDetailsViewModel(application: Application) : AndroidViewModel(application) {
private val quoteRepository: QuoteRepository = QuoteRepository(application)
private val quoteId = MutableLiveData<String>("")
val quoteAuthor = MutableLiveData<String>("")
val quoteContent = MutableLiveData<String>("")
val quoteDescription = MutableLiveData<String>("")
val quoteLastUpdate = MutableLiveData<String>("")
val onSaveClickEvent = MutableLiveData<ViewModelEvent<Unit>>()
val onCancelClickEvent = MutableLiveData<ViewModelEvent<Unit>>()
val onDeleteClickEvent = MutableLiveData<ViewModelEvent<String?>>()
var isNewQuote = false
fun setInitialData(arguments: Bundle?) {
if (arguments != null) {
val quoteData = arguments.getSerializable(KEY_DATA) as Quote
isNewQuote = false
quoteData.let { quote ->
quoteId.postValue(quote.id)
quoteAuthor.postValue(quote.author)
quoteContent.postValue(quote.quote)
quoteDescription.postValue(quote.description)
quoteLastUpdate.postValue(quote.lastUpdated.getFormattedDate())
}
} else {
isNewQuote = true
}
}
fun onViewClick(viewId: Int) {
val currentTime = Calendar.getInstance().time
when (viewId) {
R.id.actionSave -> {
if (!isNewQuote) {
val quoteData = Quote(
id = this.quoteId.value ?: "",
author = this.quoteAuthor.value ?: "",
quote = this.quoteContent.value ?: "",
description = this.quoteDescription.value ?: "",
lastUpdated = currentTime
)
quoteRepository.update(quoteData)
} else {
val quoteData = Quote(
id = UUID.randomUUID().toString(),
author = this.quoteAuthor.value ?: "",
quote = this.quoteContent.value ?: "",
description = this.quoteDescription.value ?: "",
lastUpdated = currentTime
)
quoteRepository.insert(quoteData)
}
onSaveClickEvent.postValue(ViewModelEvent(Unit))
}
R.id.actionCancel -> onCancelClickEvent.postValue(ViewModelEvent(Unit))
R.id.actionDelete -> onDeleteClickEvent.postValue(ViewModelEvent(this.quoteId.value))
}
}
fun onDeleteItemResult(guid: String?) {
val currentTime = Calendar.getInstance().time
val quoteData = Quote(
id = guid ?: "",
author = this.quoteAuthor.value ?: "",
quote = this.quoteContent.value ?: "",
description = this.quoteDescription.value ?: "",
lastUpdated = currentTime
)
quoteRepository.delete(quoteData)
}
companion object {
fun newBundle(quote: Quote?): Bundle {
return Bundle().apply {
putSerializable(KEY_DATA, quote)
}
}
}
}
Also here is code of my Quote:
#Entity(tableName = "quotes")
class Quote(
#PrimaryKey
val id: String,
val author: String,
val quote: String,
val description: String,
#ColumnInfo(name = "last_updated")
val lastUpdated: Date?
) : Serializable
And here is the code when I click on a list item
val allQuotes: LiveData<List<Quote>>
init {
allQuotes = quoteRepository.allQuotes
}
fun onListItemClick(itemIndex: Int) {
onListItemClickEvent.postValue(
ViewModelEvent(QuoteDetailsViewModel.newBundle(allQuotes.value?.getOrNull(itemIndex)))
)
}
Then I get to my view model - QuoteDetailsViewModel
Hello) I'm new in Android dev. And I have a problem with my program.
It's my model:
data class Test (val id: Int,
val numberQuestion: String,
val question: String,
val questionImageSrc: String,
val examination: Boolean,
val typeQuestion: String,
val singleChoiceAnswers: ArrayList<singleChoiceAnswer>,
val multipleChoiceAnswers: ArrayList<multipleChoiceAnswers>,
val inputAnswer: ArrayList<inputAnswer>)
data class multipleChoiceAnswers(val letter: String,
val text: String,
val correctAnswer: Boolean,
val checked: Boolean)
data class singleChoiceAnswer(val letter: String,
val text: String,
val correctAnswer: Boolean,
val checked: Boolean)
data class inputAnswer(val correctAnswer: String,
val userAnswer: String)
It's how i get the data from JSON:
private fun jsonResult(jsonString: String?) {
val jsonArray = JSONArray(jsonString)
val list = ArrayList<Test>()
val slist = ArrayList<singleChoiceAnswer>()
val mlist = ArrayList<multipleChoiceAnswers>()
val ilist = ArrayList<inputAnswer>()
for (i in 0 until jsonArray.length()){
val jsonObject = jsonArray.getJSONObject(i)
val typeQuestion = jsonObject.getString("typeQuestion")
val curentId = jsonObject.optInt("id")
val curentNQ = jsonObject.optString("numberQuestion")
val curentQ = jsonObject.optString("question")
val curentQIS = jsonObject.optString("questionImageSrc")
val curentEx = jsonObject.optBoolean("examination")
if (typeQuestion.contains("multipleChoice")){
val multipleChoiceAnswers = jsonObject.getJSONArray("multipleChoiceAnswers")
for (sc in 0 until multipleChoiceAnswers.length()){
val curentMCA = multipleChoiceAnswers.getJSONObject(sc)
val letter = curentMCA.optString("letter")
val text = curentMCA.optString("text")
val correctAnswer = curentMCA.optBoolean("correctAnswer")
val checked = curentMCA.optBoolean("checked")
mlist.add(multipleChoiceAnswers(letter, text, correctAnswer, checked))
}
}
if (typeQuestion.contains("singleChoice")){
val singleChoiceAnswer = jsonObject.getJSONArray("singleChoiceAnswers")
for (sc in 0 until singleChoiceAnswer.length()){
val curentSCA = singleChoiceAnswer.getJSONObject(sc)
val letter = curentSCA.optString("letter")
val text = curentSCA.optString("text")
val correctAnswer = curentSCA.optBoolean("correctAnswer")
val checked = curentSCA.optBoolean("checked")
slist.add(singleChoiceAnswer(letter, text, correctAnswer, checked))
}
}
if (typeQuestion.contains("input")){
val inputAnswer = jsonObject.getJSONArray("inputAnswer")
for (sc in 0 until inputAnswer.length()){
val curentIA = inputAnswer.getJSONObject(sc)
val correctAnswer = curentIA.optString("correctAnswer")
val userAnswer = curentIA.optString("userAnswer")
ilist.add(inputAnswer(correctAnswer,userAnswer))
}
}
list.add(Test(curentId, curentNQ, curentQ, curentQIS, curentEx, typeQuestion, slist, mlist, ilist))
}
val adapter = TestAdapter(list) { item ->
testAdapterItemClick(item)
}
val recView = findViewById<RecyclerView>(R.id.testRecyclerView)
recView.adapter = adapter
}
Here is link to my JSON. If you need it)
Then i am doing something like that:
private fun testAdapterItemClick(item: Test) {
val fT: FragmentTransaction = supportFragmentManager.beginTransaction()
val frag1: Fragment1 = Fragment1()
val frag2: Fragment2 = Fragment2()
if (item.typeQuestion == "input") {
val bundle = Bundle()
bundle.putString("NUMBER_KEY", item.numberQuestion)
bundle.putString("QUESTION_KEY", item.question)
if(!item.questionImageSrc.isNullOrEmpty())
bundle.putString("IMAGE_KEY", item.questionImageSrc)
frag1.setArguments(bundle)
fT.add(R.id.frameLayout, frag1)
}
if (item.typeQuestion == "singleChoice") {
val bundle = Bundle()
bundle.putString("NUMBER_KEY", item.numberQuestion)
bundle.putString("QUESTION_KEY", item.question)
val count = item.singleChoiceAnswers.size
Toast.makeText(this, count.toString(), Toast.LENGTH_LONG).show()
// bundle.putInt("COUNT_KEY", count)
for (i in 0 until count)
{
val curentSCA = item.singleChoiceAnswers[i]
bundle.putString("letterSCA$i", curentSCA.letter)
bundle.putString("textSCA$i", curentSCA.text)
}
frag2.setArguments(bundle)
fT.add(R.id.frameLayout, frag2)
I need to get ArrayList of the definite item and put it data in fragment using bundle.
But I have a problem in fragment:
public override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.fragment2, container, false)
val questionNumber = rootView.findViewById(R.id.questionNumber) as TextView
val questionText = rootView.findViewById(R.id.Question) as TextView
val questionImage = rootView.findViewById(R.id.questionImage) as ImageView
val qN : String = getArguments()?.getString("NUMBER_KEY").toString()
val quest: String = getArguments()?.getString("QUESTION_KEY").toString()
val qI: String = getArguments()?.getString("IMAGE_KEY").toString()
questionNumber.text=qN
questionText.text=quest
Picasso.get().load(qI).into(questionImage)
val radioGroup = rootView.findViewById(R.id.radioGroupSetectTest) as RadioGroup
val count : Int = getArguments()!!.getInt("COUNT_KEY")
val context = getContext()
for (i in 0 until count)
{
val curentRB = RadioButton(context)
val curLetter = getArguments()?.getString("letterSCA$i")
val curText = getArguments()?.getString("textSCA$i")
curentRB.setText(curLetter+" "+curText)
radioGroup.addView(curentRB)
}
It put the all values of singleChoiseAnswer from all items like this screen. Please, help me) I know that it is a simple problem but i realy dont understand)
Thanks in advance)
P.S. SOrry for my English)
First of all, you need to convert your Json into Kotlin classes, you can use GSON
to convert your json to kotlin data classes like this
import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
data class QuestionResponse(
#field:SerializedName("multipleChoiceAnswers")
val multipleChoiceAnswers: List<MultipleChoiceAnswersItem?>? = null,
#field:SerializedName("inputAnswer")
val inputAnswer: List<InputAnswer?>? = null,
#field:SerializedName("numberQuestion")
val numberQuestion: String? = null,
#field:SerializedName("question")
val question: String? = null,
#field:SerializedName("typeQuestion")
val typeQuestion: String? = null,
#field:SerializedName("examination")
val examination: Boolean? = null,
#field:SerializedName("id")
val id: Int? = null,
#field:SerializedName("singleChoiceAnswers")
val singleChoiceAnswers: List<MultipleChoiceAnswersItem?>? = null,
#field:SerializedName("questionImageSrc")
val questionImageSrc: String? = null
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.createTypedArrayList(MultipleChoiceAnswersItem),
parcel.createTypedArrayList(InputAnswer),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
parcel.readValue(Int::class.java.classLoader) as? Int,
parcel.createTypedArrayList(MultipleChoiceAnswersItem),
parcel.readString()
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeTypedList(multipleChoiceAnswers)
parcel.writeTypedList(inputAnswer)
parcel.writeString(numberQuestion)
parcel.writeString(question)
parcel.writeString(typeQuestion)
parcel.writeValue(examination)
parcel.writeValue(id)
parcel.writeTypedList(singleChoiceAnswers)
parcel.writeString(questionImageSrc)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<QuestionResponse> {
override fun createFromParcel(parcel: Parcel): QuestionResponse {
return QuestionResponse(parcel)
}
override fun newArray(size: Int): Array<QuestionResponse?> {
return arrayOfNulls(size)
}
}
}
import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
data class MultipleChoiceAnswersItem(
#field:SerializedName("letter")
val letter: String? = null,
#field:SerializedName("checked")
val checked: Boolean? = null,
#field:SerializedName("text")
val text: String? = null,
#field:SerializedName("correctAnswer")
val correctAnswer: Boolean? = null
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
parcel.readString(),
parcel.readValue(Boolean::class.java.classLoader) as? Boolean
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(letter)
parcel.writeValue(checked)
parcel.writeString(text)
parcel.writeValue(correctAnswer)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<MultipleChoiceAnswersItem> {
override fun createFromParcel(parcel: Parcel): MultipleChoiceAnswersItem {
return MultipleChoiceAnswersItem(parcel)
}
override fun newArray(size: Int): Array<MultipleChoiceAnswersItem?> {
return arrayOfNulls(size)
}
}
}
import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
data class InputAnswer(
#field:SerializedName("correctAnswer")
val correctAnswer: String? = null,
#field:SerializedName("userAnswer")
val userAnswer: String? = null) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readString()
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(correctAnswer)
parcel.writeString(userAnswer)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<InputAnswer> {
override fun createFromParcel(parcel: Parcel): InputAnswer {
return InputAnswer(parcel)
}
override fun newArray(size: Int): Array<InputAnswer?> {
return arrayOfNulls(size)
}
}
}
To know about Parcelable go to this link
Then when this is complete, parse the JSON like this
private fun jsonResult(jsonString: String?) {
val jsonArray = JSONArray(jsonString)
val list = ArrayList<QuestionResponse>()
val slist = ArrayList<MultipleChoiceAnswersItem>()
val mlist = ArrayList<MultipleChoiceAnswersItem>()
val ilist = ArrayList<InputAnswer>()
for (i in 0 until jsonArray.length()){
val jsonObject = jsonArray.getJSONObject(i)
val typeQuestion = jsonObject.getString("typeQuestion")
val curentId = jsonObject.optInt("id")
val curentNQ = jsonObject.optString("numberQuestion")
val curentQ = jsonObject.optString("question")
val curentQIS = jsonObject.optString("questionImageSrc")
val curentEx = jsonObject.optBoolean("examination")
if (typeQuestion.contains("multipleChoice")){
val multipleChoiceAnswers = jsonObject.getJSONArray("multipleChoiceAnswers")
for (sc in 0 until multipleChoiceAnswers.length()){
val curentMCA = multipleChoiceAnswers.getJSONObject(sc)
val letter = curentMCA.optString("letter")
val text = curentMCA.optString("text")
val correctAnswer = curentMCA.optBoolean("correctAnswer")
val checked = curentMCA.optBoolean("checked")
mlist.add(MultipleChoiceAnswersItem(letter,checked, text, correctAnswer))
}
}
if (typeQuestion.contains("singleChoice")){
val singleChoiceAnswer = jsonObject.getJSONArray("singleChoiceAnswers")
for (sc in 0 until singleChoiceAnswer.length()){
val curentSCA = singleChoiceAnswer.getJSONObject(sc)
val letter = curentSCA.optString("letter")
val text = curentSCA.optString("text")
val correctAnswer = curentSCA.optBoolean("correctAnswer")
val checked = curentSCA.optBoolean("checked")
slist.add(MultipleChoiceAnswersItem(letter, checked,text, correctAnswer))
}
}
if (typeQuestion.contains("input")){
val inputAnswer = jsonObject.getJSONArray("inputAnswer")
for (sc in 0 until inputAnswer.length()){
val curentIA = inputAnswer.getJSONObject(sc)
val correctAnswer = curentIA.optString("correctAnswer")
val userAnswer = curentIA.optString("userAnswer")
ilist.add(InputAnswer(correctAnswer,userAnswer))
}
}
val questionResponse = QuestionResponse(mlist,ilist,curentNQ,curentQ,typeQuestion,curentEx,curentId,slist,curentQIS)
//pass this questionResponse to your adapter
}
}
Then in Adapter Item click
private fun testAdapterItemClick(item: Test) {
val fT: FragmentTransaction = supportFragmentManager.beginTransaction()
val frag1: Fragment1 = Fragment1()
val frag2: Fragment2 = Fragment2()
if (item.typeQuestion == "input") {
val bundle = Bundle()
bundle.putParcelable("input", item)
frag1.setArguments(bundle)
fT.add(R.id.frameLayout, frag1)
}
// do the same for the rest
}
Then in the Fragment
public override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.fragment2, container, false)
val questionNumber = rootView.findViewById(R.id.questionNumber) as TextView
val questionText = rootView.findViewById(R.id.Question) as TextView
val questionImage = rootView.findViewById(R.id.questionImage) as ImageView
val item = arguments.getParcelable("input")
// val arraylist = arguments.getParcelableArrayList<YOUR_CLASS_TYPE>("key") //for arrays you can do it like this
//then set it in the radiobutton like this item.getCurrentText and so on
}