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())
Related
I would like to ask for help on how to retrieve data from Firestore for nested Array of Maps called "cities" into MutableList , which I then want to insert into recycler view, where the data from the “regions” are for the header and data “cities” for the regular list items.
Data for regions: MutableList , when I follow the procedure https://medium.com/firebase-tips-tricks/how-to-map-an-array-of-objects-from-cloud-firestore-to-a-list -of-objects-122e579eae10 by Alex Mamo, got fine, but data for: cities: MutableList , according same approach, is null (unable to retrive).
Can you please advise how to get data for “cities”?
P.s. somewhere I read the recommendation to iterate over "cities", but I have no idea how, please go straight for an example (ideally in Kontlin).
Code:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
…..
regionsRef.get().addOnCompleteListener { document ->
if (document.isSuccessful()) {
val documentSnapshot = document.result
// Retrieve array of maps for „regions“
val regions = documentSnapshot.toObject(RegionDocument::class.java)?.regions
// Retrieve array of maps for „cities“
val cities = documentSnapshot.toObject(CityDocument::class.java)?.cities
…
}
}
Data classes for object City:
data class City(
val cityNumber: Long? = null,
val cityName: String? = "" )
data class CityDocument(
var cities: MutableList<City>? = null)
Firestore structure:
To be able to get the data that corresponds to your document structure, you need three classes:
class Document {
var regions: MutableList<Region>? = null
}
class Region {
var cities: MutableList<City>? = null
var regionName: String? = null
var regionNumber: Long? = null
}
class City {
var cityName: String? = null
var cityNumber: Long? = null
}
And below you can find a solution for reading all cities:
val db = FirebaseFirestore.getInstance()
val docIdRef = db.collection("collName").document("docId")
docIdRef.get().addOnCompleteListener { task ->
if (task.isSuccessful) {
val document = task.result
if (document != null) {
val doc = document.toObject(Document::class.java)
if (doc != null) {
val regions = doc.regions
if (regions != null) {
for (region in regions) {
val cities = region.cities
//Do what you need to to do with your List<City>.
}
}
}
}
} else {
Log.d("TAG", task.exception!!.message!!) //Never ignore potential errors!
}
}
Now, simply replace collName and docId with the one you have in your database.
I have a Collection of Units, each unit have many fields. One of those fields is A map called Settings. The settings is <String,Any>: A->true, B->false, C->"Hello" etc.
I wish to update one of them, lets say I wish to set C to "World".
My code:
suspend fun updateData(unitID: String): Boolean = suspendCoroutine { cont ->
val firestore = FirebaseFirestore.getInstance()
firestore.collection("Units").document(unitID).get().addOnCompleteListener { it1 ->
if (it1.isSuccessful) {
val settings = it1.result.get("Settings") as? HashMap<String, Any>
if (settings != null) {
settings["C"] = "World"
val map = hashMapOf<String, Any>()
map["Settings"] = settings
firestore.collection("Units").document(unitID).update(map).addOnCompleteListener { it2->
if (it2.isSuccessful) cont.resume(true)
else cont.resumeWithException(it2.exception!!)
}
}
}
else cont.resumeWithException(it1.exception!!)
}
}
What am I doing? I am getting the map, updating the value and setting it back.
My question, is that the correct approach, can I just set the value without reading the data first?
its fine to update the data without reading it. it would save your read query limit. so don't have to do that unless there is a actual need to do.
Suggestion:
Don't name it1, it2 like that. use meaning full names.
Found it:
suspend fun updateData(unitID: String): Boolean = suspendCoroutine { cont ->
val firestore = FirebaseFirestore.getInstance()
val map = mapOf("Settings.C" to "World")
firestore.collection("Units").document(unitID).update(map).addOnCompleteListener { updateData ->
if (updateData.isSuccessful) cont.resume(true)
else cont.resume(false)
}
}
The language used is Kotlin, implemented by Android Studio.
I want to change the EditText existing in the xml of the layout folder into String type and send it as Kafka value, but I keep getting an error somewhere.
It is said that it is impossible to conclude the visible error theory. Where exactly is the problem?
class Registration() : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.Sign_Up)
val rc: Button = findViewById(R.id.Registration_Completed)
val id: EditText = findViewById(R.id.ID)
val pw: EditText = findViewById(R.id.PW)
val UserID = id.text.toString() //convert id to string
val UserPW = pw.text.toString() //convert pw to string
rc.setOnClickListener {
val intent = Intent(this, next_activity::class.java)
Producer()
Toast.makeText(this, "registration completed", Toast.LENGTH_SHORT).show()
startActivity(intent)
}
}
Below is the Producer code
class Producer {
companion object {
#JvmStatic
fun main(args: String){
val TOPIC= "test"
val SERVERS = "localhost:9092"
val configs = Properties()
configs.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, SERVERS)
configs.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
configs.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
val producer = KafkaProducer<String, String>(configs)
var record: ProducerRecord<String, String> =ProducerRecord(TOPIC,"print")
Up to this point, the output is normal.
producer.send(ProducerRecord(TOPIC, UserID))
producer.send(ProducerRecord(TOPIC, UserPW))
producer.close()
try {
producer.send(ProducerRecord<String, String> (TOPIC, "SUCCESS!"))
} catch (exception:Exception)
{
exception.printStackTrace()
}
finally { producer.close() }
The connection may not work well because the cord is partially cut.
I used the id and pw variables in the Producer by dragging the EditText to Internal fun() under the Registration class.
Producer and connection, how to pull variables, etc., function errors, etc. Which is the problem?
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()
}
So, why can I call any pair of key-value from this one, but can't from this one?
This is my code
var firstKitList = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kit_list)
val mainKitList = kitListView
val mainListViewAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, firstKitList)
mainKitList.adapter = mainListViewAdapter
db1.collection("cities").get().addOnSuccessListener { snapshot ->
for (document in snapshot.documents) {
val data = document.data
val country = data["USA"] as String
firstKitList.add(country)
}
mainListViewAdapter.notifyDataSetChanged()
}
If I switch "cities" for "KitList" and val country = data["USA"] as String for val rope = data["skipping"] as String it works... Could anyone explain this to me please?
1st Answer:
In your firestore data I don't see data for key "USA" and "skipping". Are you sure that this data are correct?
Answer for 2nd question.
I suggest you to create data class with fields you want. Then, you can map your document data to your class with code:
document.data.toObject(DataClass::class.java)
Or, if you have more than one document in QuerySnapshot:
val dataList = mutableListOf<DataClass>()
querySnapshot.documents.mapTo(dataList) { it.toObject(DataClass::class.java)}
Basing on your code, you can do this:
querySnapshot.documents.mapTo(firstKitList) { it.toObject(DataClass::class.java)}
#Edit1
this is you data model:
class City(var cityId: String,
var state: String,
var name: String,
var country: String) {
//remember to add empty constructor.
constructor() : this("", "", "", "")
}
When you tap on list on this item, create an Intent with all this data, and start new activity.
#Edit2
If you want to add document with specific id:
FirebaseFirestore.getInstance().collection("collectionName")
.document("documentId, for example LA").set(city)
If you want to pass id to previous activity, learn something about startActivityForResult method :)