(Kotlin) com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.phonetest2.model.HallData

My data class:

data class HallData(
var name:String,
var mobile:String,
var isAddInfoChecked:Boolean,
var isFanDetailChecked:Boolean,
var fanNumber:String,
var isPompDetailChecked:Boolean,
var pompNumber:String,
var isHeaterDetailChecked:Boolean,
var heaterNumber:String,
var isCircularFanDetailChecked:Boolean,
var circularFanNumber:String
)

UserAdapter:

class UserAdapter(val c: Context, val userList: MutableList<HallData>) :
    RecyclerView.Adapter<UserAdapter.UserViewHolder>() {


    inner class UserViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
        var name: TextView
        var mbNum: TextView
        var mMenus: ImageView
        var fanText: TextView
        var pompText: TextView
        var heaterText: TextView
        var circularFanText: TextView
        var fanNum: TextView
        var pompNum: TextView
        var heaterNum: TextView
        var circularFanNum: TextView

        init {
            name = v.findViewById<TextView>(R.id.mTitle)
            mbNum = v.findViewById<TextView>(R.id.mSubTitle)
            mMenus = v.findViewById(R.id.mMenus)
            mMenus.setOnClickListener { popupMenus(it) }
            fanText = v.findViewById(R.id.fan_text)
            pompText = v.findViewById(R.id.pomp_text)
            heaterText = v.findViewById(R.id.heater_text)
            circularFanText = v.findViewById(R.id.circular_text)
            fanNum = v.findViewById(R.id.fan_number)
            pompNum = v.findViewById(R.id.pomp_number)
            heaterNum = v.findViewById(R.id.heater_number)
            circularFanNum = v.findViewById(R.id.circular_number)

            fanText.visibility = View.GONE
            pompText.visibility = View.GONE
            heaterText.visibility = View.GONE
            circularFanText.visibility = View.GONE
            fanNum.visibility = View.GONE
            pompNum.visibility = View.GONE
            heaterNum.visibility = View.GONE
            circularFanNum.visibility = View.GONE

        }

        private fun popupMenus(v: View) {
            val position = userList[adapterPosition]
            val popupMenus = PopupMenu(c, v)
            popupMenus.inflate(R.menu.show_menu)
            popupMenus.setOnMenuItemClickListener {
                when (it.itemId) {
                    R.id.editText -> {
                        val v = LayoutInflater.from(c).inflate(R.layout.add_hall, null)
                        val name = v.findViewById<EditText>(R.id.userName)
                        val number = v.findViewById<EditText>(R.id.userNo)
                        val addInfoCheckBox = v.findViewById<CheckBox>(R.id.add_info_checkBox)
                        val fanCheckBox = v.findViewById<CheckBox>(R.id.fan_checkbox)
                        val pompCheckBox = v.findViewById<CheckBox>(R.id.pomp_checkbox)
                        val heaterCheckBox = v.findViewById<CheckBox>(R.id.heater_checkbox)
                        val circularFanCheckBox = v.findViewById<CheckBox>(R.id.circular_checkbox)
                        val fanNumberPicker = v.findViewById<NumberPicker>(R.id.fan_number_picker)
                        val pompNumberPicker = v.findViewById<NumberPicker>(R.id.pomp_number_picker)
                        val heaterNumberPicker =
                            v.findViewById<NumberPicker>(R.id.heater_number_picker)
                        val circularFanNumberPicker =
                            v.findViewById<NumberPicker>(R.id.circular_number_picker)
                        val fanLayout = v.findViewById<ConstraintLayout>(R.id.fan_layout)
                        val pompLayout = v.findViewById<ConstraintLayout>(R.id.pomp_layout)
                        val heaterLayout = v.findViewById<ConstraintLayout>(R.id.heater_layout)
                        val circularFanLayout = v.findViewById<ConstraintLayout>(R.id.circular_layout)
                        val fanNumberPreview = v.findViewById<TextView>(R.id.fan_number_preview)
                        val pompNumberPreview = v.findViewById<TextView>(R.id.pomp_number_preview)
                        val heaterNumberPreview = v.findViewById<TextView>(R.id.heater_number_preview)
                        val circularFanNumberPreview = v.findViewById<TextView>(R.id.circular_number_preview)
                        var fanNumber = 0
                        var pompNumber = 0
                        var heaterNumber = 0
                        var circularFanNumber = 0

                        addInfoCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
                            if (addInfoCheckBox.isChecked) {
                                Toast.makeText(c, "Checked", Toast.LENGTH_SHORT).show()
                                fanLayout.visibility = View.VISIBLE
                                pompLayout.visibility = View.VISIBLE
                                heaterLayout.visibility = View.VISIBLE
                                circularFanLayout.visibility = View.VISIBLE
                                fanNumberPicker.visibility = View.GONE
                                fanNumberPreview.visibility = View.GONE
                                pompNumberPicker.visibility = View.GONE
                                pompNumberPreview.visibility = View.GONE
                                heaterNumberPicker.visibility = View.GONE
                                heaterNumberPreview.visibility = View.GONE
                                circularFanNumberPicker.visibility = View.GONE
                                circularFanNumberPreview.visibility = View.GONE
                                //Fan Setting:
                                fanCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
                                    if (fanCheckBox.isChecked) {
                                        fanCheckBox.setBackgroundResource(R.drawable.green_stroke)
                                        fanNumberPicker.visibility = View.VISIBLE
                                        fanNumberPreview.visibility = View.VISIBLE
                                        fanNumberPicker.minValue = 0
                                        fanNumberPicker.maxValue = maxNumberPickerValue
                                        fanNumberPicker.setOnValueChangedListener { picker, oldVal, newVal ->
                                            fanNumberPreview.text = "تعداد فن : $newVal"
                                            fanNumber = newVal
                                        }
                                    } else {
                                        fanNumberPicker.visibility = View.GONE
                                        fanNumberPreview.visibility = View.GONE
                                        fanCheckBox.setBackgroundResource(R.drawable.red_stroke)
                                    }
                                }


                                //Pomp Setting:
                                pompCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
                                    if (pompCheckBox.isChecked) {
                                        pompCheckBox.setBackgroundResource(R.drawable.green_stroke)
                                        pompNumberPicker.visibility = View.VISIBLE
                                        pompNumberPreview.visibility = View.VISIBLE
                                        pompNumberPicker.minValue = 0
                                        pompNumberPicker.maxValue = maxNumberPickerValue
                                        pompNumberPicker.setOnValueChangedListener { picker, oldVal, newVal ->
                                            pompNumberPreview.text = "تعداد پمپ : $newVal"
                                            pompNumber = newVal
                                        }
                                    } else {
                                        pompCheckBox.setBackgroundResource(R.drawable.red_stroke)
                                        pompNumberPicker.visibility = View.GONE
                                        pompNumberPreview.visibility = View.GONE
                                    }
                                }

                                //Heater Setting:
                                heaterCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
                                    if (heaterCheckBox.isChecked) {
                                        heaterCheckBox.setBackgroundResource(R.drawable.green_stroke)
                                        heaterNumberPicker.visibility = View.VISIBLE
                                        heaterNumberPreview.visibility = View.VISIBLE
                                        heaterNumberPicker.minValue = 0
                                        heaterNumberPicker.maxValue = maxNumberPickerValue
                                        heaterNumberPicker.setOnValueChangedListener { picker, oldVal, newVal ->
                                            heaterNumberPreview.text = "تعداد هیتر : $newVal"
                                            heaterNumber = newVal
                                        }
                                    } else {
                                        heaterCheckBox.setBackgroundResource(R.drawable.red_stroke)
                                        heaterNumberPicker.visibility = View.GONE
                                        heaterNumberPreview.visibility = View.GONE
                                    }
                                }

                                //CircularFan Setting:
                                circularFanCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
                                    if (circularFanCheckBox.isChecked) {
                                        circularFanCheckBox.setBackgroundResource(R.drawable.green_stroke)
                                        circularFanNumberPicker.visibility = View.VISIBLE
                                        circularFanNumberPreview.visibility = View.VISIBLE
                                        circularFanNumberPicker.minValue = 0
                                        circularFanNumberPicker.maxValue = maxNumberPickerValue
                                        circularFanNumberPicker.setOnValueChangedListener { picker, oldVal, newVal ->
                                            circularFanNumberPreview.text = "تعداد فن : $newVal"
                                            circularFanNumber = newVal
                                        }


                                    } else {
                                        circularFanCheckBox.setBackgroundResource(R.drawable.red_stroke)
                                        circularFanNumberPicker.visibility = View.GONE
                                        circularFanNumberPreview.visibility = View.GONE
                                    }
                                }


                            } else {
                                Toast.makeText(c, "Unchecked", Toast.LENGTH_SHORT).show()
                                fanLayout.visibility = View.GONE
                                pompLayout.visibility = View.GONE
                                heaterLayout.visibility = View.GONE
                                circularFanLayout.visibility = View.GONE
                            }
                        }

                        name.setText(hallData[adapterPosition].name)
                        number.setText(hallData[adapterPosition].mobile)
                        AlertDialog.Builder(c)
                            .setView(v)
                            .setPositiveButton("ویرایش") { dialog, _ ->
                                position.name = name.text.toString()
                                position.mobile = number.text.toString()
                                Names[adapterPosition] = name.text.toString()
                                Phones[adapterPosition] = number.text.toString()
                                hallData[adapterPosition] = HallData(name.text.toString(),number.text.toString(),addInfoCheckBox.isChecked,fanCheckBox.isChecked,fanNumber.toString(),pompCheckBox.isChecked,pompNumber.toString(),heaterCheckBox.isChecked,heaterNumber.toString(),circularFanCheckBox.isChecked,circularFanNumber.toString())
                                notifyDataSetChanged()
                                Toast.makeText(c, "داده مورد نظر ویرایش شد", Toast.LENGTH_SHORT)
                                    .show()
                                dialog.dismiss()

                            }
                            .setNegativeButton("لغو") { dialog, _ ->
                                dialog.dismiss()

                            }
                            .create()
                            .show()

                        true
                    }

                    R.id.delete -> {
                        /**set delete*/
                        AlertDialog.Builder(c)
                            .setTitle("حذف «${Names[adapterPosition]}»")
                            .setIcon(R.drawable.ic_warning)
                            .setMessage("آیا از حذف این داده مطمئن هستید؟")
                            .setPositiveButton("بله") { dialog, _ ->
                                userList.removeAt(adapterPosition)
                                //Log.d("TAG","Names -> "+Data.Phones)
                                Data.number--
                                Names.removeAt(adapterPosition)
                                Phones.removeAt(adapterPosition)
                                hallData.removeAt(adapterPosition)
                                //Log.d("TAG","Message -> Removed")
                                notifyDataSetChanged()
                                Toast.makeText(c, "داده مورد نظر حذف شد", Toast.LENGTH_SHORT).show()
                                dialog.dismiss()
                            }
                            .setNegativeButton("خیر") { dialog, _ ->
                                dialog.dismiss()
                            }
                            .create()
                            .show()

                        true
                    }

                    else -> true
                }

            }
            popupMenus.show()
            val popup = PopupMenu::class.java.getDeclaredField("mPopup")
            popup.isAccessible = true
            val menu = popup.get(popupMenus)
            menu.javaClass.getDeclaredMethod("setForceShowIcon", Boolean::class.java)
                .invoke(menu, true)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val v = inflater.inflate(R.layout.hall_item, parent, false)
        return UserViewHolder(v)
    }

    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val newList = userList[position]
        holder.name.text = newList.name
        holder.mbNum.text = newList.mobile
        if(Data.hallData[position].isAddInfoChecked){
            holder.fanNum.text = newList.fanNumber.toString()
            holder.pompNum.text = newList.pompNumber.toString()
            holder.heaterNum.text = newList.heaterNumber.toString()
            holder.circularFanNum.text = newList.circularFanNumber.toString()

            holder.fanText.visibility = View.VISIBLE
            holder.pompText.visibility = View.VISIBLE
            holder.heaterText.visibility = View.VISIBLE
            holder.circularFanText.visibility = View.VISIBLE
            holder.fanNum.visibility = View.VISIBLE
            holder.pompNum.visibility = View.VISIBLE
            holder.heaterNum.visibility = View.VISIBLE
            holder.circularFanNum.visibility = View.VISIBLE
        }else{
            holder.fanText.visibility = View.GONE
            holder.pompText.visibility = View.GONE
            holder.heaterText.visibility = View.GONE
            holder.circularFanText.visibility = View.GONE
            holder.fanNum.visibility = View.GONE
            holder.pompNum.visibility = View.GONE
            holder.heaterNum.visibility = View.GONE
            holder.circularFanNum.visibility = View.GONE
        }
    }

    override fun getItemCount(): Int {
        return userList.size
    }
}

MainActivity:

class MainActivity : AppCompatActivity() {

    private lateinit var addsBtn: FloatingActionButton
    private lateinit var recv: RecyclerView
    private lateinit var userList: MutableList<HallData>
    private lateinit var userAdapter: UserAdapter
    private lateinit var addInfoCheckBox: CheckBox
    private var backPressedTime = 0L
    lateinit var jsonString:String

    var gson = Gson()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        /**set List*/
        userList = ArrayList()
        /**set find Id*/
        addsBtn = findViewById(R.id.addingBtn)
        recv = findViewById(R.id.mRecycler)
        /**set Adapter*/
        userAdapter = UserAdapter(this,userList)
        /**setRecycler view Adapter*/
        recv.layoutManager = LinearLayoutManager(this)
        recv.adapter = userAdapter
        /**set Dialog*/
        addsBtn.setOnClickListener { addInfo() }
        Data.hallData.clear()
        Data.number=0
        Data.Names.clear()
        Data.Phones.clear()

        val sharedPrefsMain = getSharedPreferences("my_prefs", MODE_PRIVATE)
        val json_saved = sharedPrefsMain.getString("JsonHallData",null)
        val after_json_saved = gson.fromJson(json_saved, mutableListOf<HallData>()::class.java)

        if(!after_json_saved.isNullOrEmpty()){
        for (i in 0 until after_json_saved.size){
            try }
                userList.add(after_json_saved[i])
                Data.hallData.add(after_json_saved[i])

            } catch (e:Exception){
                Log.e("ERROR",e.message.toString())
            }

        }

        }
    }

    private fun addInfo() {
        val inflter = LayoutInflater.from(this)
        val v = inflter.inflate(R.layout.add_hall,null)
        /**set view*/
        val userName = v.findViewById<EditText>(R.id.userName)
        val userNo = v.findViewById<EditText>(R.id.userNo)

        val addInfoCheckBox = v.findViewById<CheckBox>(R.id.add_info_checkBox)
        val fanCheckBox = v.findViewById<CheckBox>(R.id.fan_checkbox)
        val pompCheckBox = v.findViewById<CheckBox>(R.id.pomp_checkbox)
        val heaterCheckBox = v.findViewById<CheckBox>(R.id.heater_checkbox)
        val circularFanCheckBox = v.findViewById<CheckBox>(R.id.circular_checkbox)
        val fanNumberPicker = v.findViewById<NumberPicker>(R.id.fan_number_picker)
        val pompNumberPicker = v.findViewById<NumberPicker>(R.id.pomp_number_picker)
        val heaterNumberPicker =
            v.findViewById<NumberPicker>(R.id.heater_number_picker)
        val circularFanNumberPicker =
            v.findViewById<NumberPicker>(R.id.circular_number_picker)
        val fanLayout = v.findViewById<ConstraintLayout>(R.id.fan_layout)
        val pompLayout = v.findViewById<ConstraintLayout>(R.id.pomp_layout)
        val heaterLayout = v.findViewById<ConstraintLayout>(R.id.heater_layout)
        val circularFanLayout = v.findViewById<ConstraintLayout>(R.id.circular_layout)
        val fanNumberPreview = v.findViewById<TextView>(R.id.fan_number_preview)
        val pompNumberPreview = v.findViewById<TextView>(R.id.pomp_number_preview)
        val heaterNumberPreview = v.findViewById<TextView>(R.id.heater_number_preview)
        val circularFanNumberPreview = v.findViewById<TextView>(R.id.circular_number_preview)
        var fanNumber = 0
        var pompNumber = 0
        var heaterNumber = 0
        var circularFanNumber = 0

        addInfoCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
            if (addInfoCheckBox.isChecked) {
                fanLayout.visibility = View.VISIBLE
                pompLayout.visibility = View.VISIBLE
                heaterLayout.visibility = View.VISIBLE
                circularFanLayout.visibility = View.VISIBLE
                fanNumberPicker.visibility = View.GONE
                fanNumberPreview.visibility = View.GONE
                pompNumberPicker.visibility = View.GONE
                pompNumberPreview.visibility = View.GONE
                heaterNumberPicker.visibility = View.GONE
                heaterNumberPreview.visibility = View.GONE
                circularFanNumberPicker.visibility = View.GONE
                circularFanNumberPreview.visibility = View.GONE
                //Fan Setting:
                fanCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
                    if (fanCheckBox.isChecked) {
                        fanCheckBox.setBackgroundResource(R.drawable.green_stroke)
                        fanNumberPicker.visibility = View.VISIBLE
                        fanNumberPreview.visibility = View.VISIBLE
                        fanNumberPicker.minValue = 0
                        fanNumberPicker.maxValue = Data.maxNumberPickerValue
                        fanNumberPicker.setOnValueChangedListener { picker, oldVal, newVal ->                                fanNumberPreview.text = "تعداد فن : $newVal"
                            fanNumber = newVal
                        }
                    } else {
                        fanNumberPicker.visibility = View.GONE
                        fanNumberPreview.visibility = View.GONE
                        fanCheckBox.setBackgroundResource(R.drawable.red_stroke)
                    }
                }


                //Pomp Setting:
                ...

                //Heater Setting:
                ...

                //CircularFan Setting:
...


            } else {
                fanLayout.visibility = View.GONE
                pompLayout.visibility = View.GONE
                heaterLayout.visibility = View.GONE
                circularFanLayout.visibility = View.GONE
            }
        }

        val addDialog = AlertDialog.Builder(this)
        addDialog.setView(v)


        addDialog.setPositiveButton("افزودن"){
                dialog,_->


            val names = userName.text.toString()
            val number = userNo.text.toString()
            userList.add(HallData(
                names,
                number,
                addInfoCheckBox.isChecked,
                fanCheckBox.isChecked,
                fanNumber.toString(),
                pompCheckBox.isChecked,
                pompNumber.toString(),
                heaterCheckBox.isChecked,
                heaterNumber.toString(),
                circularFanCheckBox.isChecked,
                circularFanNumber.toString()
            ))
            userAdapter.notifyDataSetChanged()
            Data.number++
            Data.Names.add(names)
            Data.Phones.add(number)

                Data.hallData.add(HallData(
                    names,
                    number,
                    addInfoCheckBox.isChecked,
                    fanCheckBox.isChecked,
                    fanNumber.toString(),
                    pompCheckBox.isChecked,
                    pompNumber.toString(),
                    heaterCheckBox.isChecked,
                    heaterNumber.toString(),
                    circularFanCheckBox.isChecked,
                    circularFanNumber.toString()
                    ))

            Toast.makeText(this,"داده مورد نظر با موفقیت اضافه شد", Toast.LENGTH_SHORT).show()
            dialog.dismiss()
            }

        addDialog.setNegativeButton("لغو"){
                dialog,_->
            dialog.dismiss()
            Toast.makeText(this,"افزودن داده مورد نظر لغو شد", Toast.LENGTH_SHORT).show()

        }
        addDialog.create()
        addDialog.show()
    }

    /**ok now run this */
    override fun onPause() {
        super.onPause()
        val sharedPrefsOnPause = getSharedPreferences("my_prefs", MODE_PRIVATE)
        val mEditor = sharedPrefsOnPause.edit()
        mEditor.remove("Names")
        mEditor.remove("Phone")
        mEditor.remove("JsonHallData")



        jsonString = gson.toJson(Data.hallData)
        Log.d("JSON TAG","OnPause jsonString -> $jsonString")
        mEditor.putString("JsonHallData",jsonString)
        mEditor.apply()
    }

    override fun onBackPressed() {
        if(backPressedTime + 2000 > System.currentTimeMillis()){
            super.onBackPressed()
        } else{
            Toast.makeText(this, "برای خروج از برنامه، دوباره دکمه بازگشت را فشار دهید\n", Toast.LENGTH_SHORT).show()
        }
        backPressedTime = System.currentTimeMillis()

    }

}

In onPause, users’ hall details are to be saved in sharedpreferences

First, hall details convert to Json (String) and after that jsonString will be saved in sharedpreferences:

    jsonString = gson.toJson(Data.hallData)
    
    mEditor.putString("JsonHallData",jsonString)
    mEditor.apply()

Now, When user opens the app, I have a variable "json_saved" that receive jsonString from sharedpreferences

And, a variable "after_json_saved" that uses gson to convert json to my data class mutableList

val after_json_saved = gson.fromJson(json_saved, mutableListOf<HallData>()::class.java)

When I log this variable, after reopening app my saved data is correctly shown in this variable but the app crashes!

And this variable should be added to userList (and to my hallData variable in my object "Data" -> unimportant)

But the app crashes with this error:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.phonetest2.model.HallData

And the error contains these lines of UserAdapter (Error is related to onBindViewHolder):

  1. class UserAdapter(val c: Context, val userList: MutableList<HallData>) :
  2. val newList = userList[position]

I have read possible answers related to this error but my problem has not been solved

Your help will be appreciated

>Solution :

It’s because of the type erasure in mutableListOf<HallData>()::class.java. It loses the information that it was HallData and deserializes it as LinkedTreeMap

Please try replacing val after_json_saved = gson.fromJson(json_saved, mutableListOf<HallData>()::class.java) with val after_json_saved = gson.fromJson(json_saved, object : TypeToken<MutableList<HallData>>() {})

Leave a Reply