I want to store 2D array using shared preference ?
Here I am trying to store 2D array in shared preference from one activity and after that i can load it in another activity using previously stored 2D array but i am not able to store 2D array in shared preference.
val _rMsg = intent.getStringArrayExtra(rKey)
val inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val parent = _class11_
val _arData = arrayListOf<Array<String>>()
val sharedPreferences = getSharedPreferences("shared pref", Context.MODE_PRIVATE)
val gson = Gson()
val backJson = sharedPreferences.getString("task_li",null)
val type = TypeToken<ArrayList<>>() {}.type
_arData.add(gson.fromJson(backJson,type))
try {
_arData.add(_rMsg)
val edit = sharedPreferences.edit()
val json = gson.toJson(_arData)
edit.putString("task_li",json)
edit.apply()
for (i in _arData) {
val cardView = inflater.inflate(R.layout._preset_layout, null)
val mT = cardView.findViewById<TextView>(R.id._title__)
mT.text = i[0].toString()
parent.addView(cardView)
}
} catch (ex: Exception) {
}
We can use ObjectSerializer. [ https://github.com/apache/pig/blob/89c2e8e76c68d0d0abe6a36b4e08ddc56979796f/src/org/apache/pig/impl/util/ObjectSerializer.java ] this awesome class permit you to simple serialize and deserialize every kind of object, so you can simply save them as string into shared. You can store it like this :
val mArrayTest = arrayListOf<Array<String>>()
mArrayTest.add(arrayOf("1","3"))
mArrayTest.add(arrayOf("2","4"))
edit.putString("mArrayTest",ObjectSerializer.serialize(mArrayTest)).commit()
and get it like this :
val mTestStr = pref.getString("mArrayTest",null)
if (mTestStr != null) {
val mTestStr2 = ObjectSerializer.deserialize(mTestStr) as ArrayList<Array<String>>
Toast.makeText(this, mTestStr2[0][1].toString(), Toast.LENGTH_SHORT).show()
}
Related
I have a global object that store 2 custom class objects, something like this:
/////// Separated object file ////////
object ApplicationData {
var profiledata:ProfileData = ProfileData(null)
var OVOlists = ArrayList<OVOList>()
}
/////// Separated class file ////////
class OVOList (
private var OVOIcon: Int,
private var OVOName: String?,
private var OVOPlace: String?,
private var OVOstatus: Int
) :Parcelable {
private var Humidity:String? =""
private var Temperature:String? = ""
private var PH:String? =""
private var WaterLvl :String? = ""
constructor(parcel: Parcel) : this(
parcel.readValue(Int::class.java.classLoader) as Int,
parcel.readString(),
parcel.readString(),
parcel.readValue(Int::class.java.classLoader) as Int
) {
Humidity = parcel.readString()
Temperature = parcel.readString()
PH = parcel.readString()
WaterLvl = parcel.readString()
} ... + setters , getters and parcel lines
/////// separated class file ////////
class ProfileData(private var email:String?):Parcelable {
private var token:String? =""
private var profile_image: String? =""
private var profile_image_path:String? = ""
private var nombre:String? = ""
private var uid:String? = ""
constructor(parcel: Parcel) : this(
parcel.readString(),
) {
token=parcel.readString()
profile_image = parcel.readString()
profile_image_path = parcel.readString()
nombre = parcel.readString()
uid=parcel.readString()
} ... + setters,getters and parcel lines
The classes are parcelable, because i was moving some information via bundles, but now im using this global object so there is no need to keep them like that.
But the question is how to store the whole object into memory, i have try the Gson/preferences aproach but i cannot make it work :(, it doesnt store the object, maybe its because it has 2 custom class objects inside, i dont think the parcelable attribute should affect. I made something like this:
//write//
mprefs.edit().putString("MyappData",gson.toJson(ApplicationData)).apply()
//read//
String json = mprefs.getString("MyappData", "")
val obj = gson.fromJson(json, ApplicationData::java.class)
ApplicationData.profiledata = obj.profiledata
ApplicationData.OVOlists = obj.OVOlists
It seems that its failing in the writing part , any ideas what to do?
You can save them as Strings (json format ) and the covert to Object ,as you are doing , I think you should use data classes and use #Parcelize and avoid using too much code
Thanks to all your help, i made this work with Gson, i created inside the object a function that stores and retrieves the data from/to pref. i just pass the context to it, i think was not working properly because of the parcelable part inside the classes. The final object is this:
object ApplicationData {
var profiledata:ProfileData = ProfileData(null)
var OVOlists = ArrayList<OVOList>()
fun save(context: Context){
val sharedPreference = context.getSharedPreferences("OVO_PREF", Context.MODE_PRIVATE)
val prefsEditor = sharedPreference.edit()
val gson = Gson()
val json = gson.toJson(ApplicationData)
prefsEditor.putString("AppData", json)
Log.e("saving in preferences",json)
prefsEditor.apply()
}
fun retrieveData(context: Context):Boolean{
val sharedPreference = context.getSharedPreferences("OVO_PREF", Context.MODE_PRIVATE)
val gson = Gson()
val json = sharedPreference.getString("AppData", "")
val obj = gson.fromJson(json, ApplicationData::class.java)
if(obj!=null){
profiledata = obj.profiledata
OVOlists = obj.OVOlists
//Log.e("retrieve info",obj.OVOlists[0].getOVOName()!!)
return true
}else{
return false }
}
The two custom classes now are regular and normal classes, with setters and getters. So the main object can save its own data calling ApplicationData.save(context)
I'm trying to save data from my fragment in Kotlin, I tried to use shared preference for that since I'm only saving strings in the fragment. I don't understand why the data is not saving. I'm using them both in OnViewCreated.
First Fragment IMAGE [1]: https://i.stack.imgur.com/uqlUt.png
Second Fragment Image [2]: https://i.stack.imgur.com/ifpRU.png
FirstFragment
val sharedPreferences =
requireActivity().applicationContext.getSharedPreferences("sharedPref",Context.MODE_PRIVATE)
val price = sharedPreferences.getString("PRICE",null)
binding.priceId.text = price
val expense = sharedPreferences.getString("EXPENSE",null)
binding.priceId1.text = expense
Second Fragment with EditText
val insertedText : String = binding.itemPrice.text.toString()
val insertedText2 : String = binding.itemPrice2.text.toString()
val sharedPreferences = requireActivity().applicationContext.getSharedPreferences("sharedPref",Context.MODE_PRIVATE)
val editor : SharedPreferences.Editor = sharedPreferences.edit()
editor.apply {
putString("PRICE",insertedText)
putString("EXPENSE",insertedText2)
}
editor.apply()
Toast.makeText(requireContext(),"Saved", Toast.LENGTH_LONG).show()
Here's how I'm using sharedPreferences with fragment
//Getting the sharedPreferences
val appContext = requireContext().applicationContext
var prefs = appContext.getSharedPreferences("sharedPref", Context.MODE_PRIVATE)
prefs.edit().putString("PRICE", insertedText).apply();
I have this preference manager
class JournalManager {
lateinit var pref: SharedPreferences
lateinit var editor: SharedPreferences.Editor
lateinit var con: Context
var PRIVATE_MODE: Int = 0
constructor(con: Context?) {
if (con != null) {
this.con = con
}
if (con != null) {
pref = con.getSharedPreferences(PREF_NAME,PRIVATE_MODE)
}
editor = pref.edit()
}
companion object {
val PREF_NAME: String = "Journal"
val KEY_TEXT: String = "text"
}
fun createJournalSession(
text: EditText,
) {
editor.putString(KEY_TEXT, text.toString())
editor.commit()
}
fun getJournalDetails(): Map<String, String>
{
var journal: Map<String, String> = HashMap<String, String>()
pref.getString(KEY_TEXT,null)?.let { (journal as HashMap).put(KEY_TEXT, it) }
return journal
}
fun DeleteJournal() {
editor.clear()
editor.commit()
var i: Intent = Intent(con, JournalActivity::class.java)
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
con.startActivity(i)
}
}
And I'm looking for solution to add objects in it but my app is crashing, here is a sample of how I try to add object
lateinit var journalSession: JournalManager
override fun onCreate(savedInstanceState: Bundle?) {...}
fun openDialog() {
val dialog = MaterialDialog(this)
.noAutoDismiss()
.customView(R.layout.layout_new_journal)
//set initial preferences
dialog.findViewById<Button>(R.id.save_btn).setOnClickListener{
val note = dialog.findViewById<EditText>(R.id.new_journal_input)
//add to preference
journalSession.createJournalSession(
note
)
dialog.dismiss()
}
dialog.findViewById<Button>(R.id.cancel_btn).setOnClickListener {
dialog.dismiss()
}
dialog.show()
}
Any suggestion?
Update
Let me make it clear what I'm looking for:
At the beginning I do not have any data, nor shared preference in device (shared preference will create when user saves it's first journal).
2.When user adds new journal it suppose to be stored (as of sample) like this
journal [{
note="this was user first note"
}]
Then when next time user adds new journal, it suppose to be stored (as of sample) like this
journal [{
note="this was user first note"
},
{note="this was user second note"
}]
and so on...
PS So far all videos, articles anything else I've found on web was with same logic: (they've had a List and then store that list into preferences!), my case is not like that, I do not have any list to store my list will be created one by one, during the time just like any real world apps.
Now, any idea how to make it happen, and what should I change in my code?
SharedPreferences saves primitive type data and Srting. For saving object like List you can use GSON library (by Google) to convert the object into JSON String.
1. Import Dependency:
implementation 'com.google.code.gson:gson:2.8.6'
2. Basic Usage:
val studentJsonString = Gson().toJson(student) //object -> String
val student = Gson().fromJson(studentJsonString, Student.class) //String -> object
3. For List:
val typeToken = TypeToken<List<Student>>(){}
val students = Gson().fromJson(studentsJsonString, typeToken.getType())
I Have Created A Function That Dynamically Makes A Textview And Assigns The Values Of Shared Preferences To It.Now I Want To Make A New TextView Each Time The User Enters Data In It
There are 5 Shared Preferences - Day , Medicine ,Time , HowMuch ,When
val shrd = getSharedPreferences("Add$dayselected", Context.MODE_PRIVATE)
val editor = shrd.edit()
editor.putString("medicine", medicine)
editor.putString("day", dayselected)
editor.putString("whenSelected", whenselected)
editor.putString("medicineSelected", medicineselected)
editor.putString("time", timeselected)
editor.apply()
Toast.makeText(this#Add, "Saved To Internal Database", Toast.LENGTH_SHORT).show()
These Are The Preferences
val pref = getSharedPreferences("AddFriday", MODE_PRIVATE)
val dayA = pref?.getString("day", "NOT FOUND ").toString()
val medicinea = pref?.getString("medicine", "NOT FOUND ").toString()
val whenSel = pref?.getString("whenSelected", "NOT FOUND ").toString()
val mediselec = pref?.getString("medicineSelected", "NOT FOUND ").toString()
val time = pref?.getString("time", "NOT FOUND ").toString()
Now I Have Assigned The Value Of Each Preference To A TextView
If The User Enters New Data I Want The New Textview To Have The New Data And The Old To Remain The Same
Functions To add Textviews
private fun add_view(data: String, id: Int): View {
val text = TextView(applicationContext)
text.setBackgroundColor(Color.rgb(255, 229, 229))
text.width = 100
text.height = 50
text.x = 21F
text.y = 88F
text.id = id
text.text = data
return text
}
private fun add_row(dayA: String, medicinea: String, whenSel: String, mediselec: String, time: String) {
val layout: ConstraintLayout? = fridaylayout
val dayview = add_view(dayA, R.id.dayf)
val medicineview = add_view(medicinea, R.id.medicinef)
medicineview?.x = +100F
val whenselview = add_view(whenSel, R.id.whenf)
whenselview?.x = +200F
val mediselview = add_view(mediselec, R.id.howmuchf)
mediselview?.x = +300F
val timeview = add_view(time, R.id.timef)
timeview?.x = +400F
layout?.addView(dayview)
layout?.addView(medicineview)
layout?.addView(whenselview)
layout?.addView(mediselview)
layout?.addView(timeview)
}
Thank You
Asad
I am new in using gson. I have tried several times to insert a Json Object inside a Json Array in Kotlin. I was able to successfully create the Json Array with Json Object and save it to internal storage. However, I wasn't able to insert Json Object inside it with this code. Any suggestions on how I would be able to achieve this? I've tried to get the file from internal storage and I couldn't fromJson it so I'm not sure if this idea would work. The data in the array are all strings. Here is my code:
fun save(){
var gson = Gson()
val filename = "name"
val file = context?.getFileStreamPath(filename)
if(file == null || !file.exists()){
val array= ArrayList<arraylist>()
array.add(arraylist("1","2","3"))
var json:String=gson.toJson(array).replace("\\n", "\n")
context?.openFileOutput(filename, Context.MODE_PRIVATE).use {
it?.write(json.toByteArray())
}
}
else{
val file = File(context?.filesDir, filename)
val contents = file.readText()
val gson = GsonBuilder().create()
val content = gson.fromJson(contents, arraylist::class.java)
content.add(arraylist("1","2","3"))
var json:String=gson.toJson(content).replace("\\n", "\n")
}
}
I finally fixed this by reading it then saving it to internal storage. This is inside the else{} statement:
val file1 = File(context?.filesDir, filename)
val contents = file1.readText()
val array = gson.fromJson(contents, Array<arraylist>::class.java)
val arrayList = ArrayList(array.toMutableList())
arrayList.add(devices("Finally","Works","Wow"))
val json: String = gson.toJson(arrayList).replace("\\n", "\n")
context?.openFileOutput(filename, Context.MODE_PRIVATE).use {
it?.write(json.toByteArray())
}