I am trying to read data from my firebase realtime database to a TextView. But every time it shows null in TextView. I want to read single user data. I want to read data when user give input.
My Data Structure look like this..
{
"Date": {
"04-10-2019": {
"-LqR-e2UJLJCccqfgGi1":{
address: Dhaka
date: 04-10-2019
name: Mark
phoneNo: 017#######
serialNo: -LqR-e2UJLJCccqfgGi1
type: New
},
},
"05-10-2019": {
"-LqU-e2UJLJCDcqfgGi9":{
address: Dhaka
date: 04-10-2019
name: Tony
phoneNo: 017#######
serialNo: -LqU-e2UJLJCDcqfgGi9
type: OLd
},
}
}
The code that I am trying.
class Info(
val serialNo: String? = "",
val name: String = "",
val address: String = "",
val phoneNo: String = "",
val date: String = "",
var type: String = ""
)
private fun saveInfo() {
// Edit Text Field
val name = editTextName.text.toString().trim()
if (name.isEmpty()) {
editTextName.error = "Please Enter Your Name"
return
}
val address = editTextAddress.text.toString().trim()
if (address.isEmpty()) {
editTextAddress.error = "Please Enter Your Address"
return
}
val phoneNo = editTextPhoneNo.text.toString().trim()
if (phoneNo.isEmpty()) {
editTextPhoneNo.error = "Please Enter Your Phone Number"
return
}
val date = dateText.text.toString().trim()
//Radio Button
var type = ""
when {
checkboxNew.isChecked -> type += "New"
checkboxOld.isChecked -> type += "Old"
radioGroup.checkedRadioButtonId <= 0 -> {
Toast.makeText(applicationContext, "Please Check New or Old", Toast.LENGTH_LONG)
.show()
return
}
}
val current = LocalDateTime.now()
val formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy")
val formatted = current.format(formatter)
val myRef = FirebaseDatabase.getInstance().getReference("Date").child(formatted)
myRef.orderByChild(formatted).startAt("28-09-2019").endAt("31-12-2070")
val patientId = myRef.push().key
val patient = Info(patientId, name, address, phoneNo, date, type)
myRef.child((patientId).toString()).setValue(patient).addOnCompleteListener {
Toast.makeText(applicationContext, "Info saved Successfully", Toast.LENGTH_LONG).show()
myRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (data in dataSnapshot.children) {
val user = data.child(formatted).value.toString()
dataText.text = user
}
}
override fun onCancelled(error: DatabaseError) {
}
})
}
}
I want to show the data into a textview when the user give input and hit a button.
If you are trying to read the date attribute from the database then change this :
val user = data.child(formatted).value.toString()
Into this:
val user = data.child("date").value.toString()
Inside the child() you need to pass the name of the attribute.
Related
I have this app that someone can delete his document at any time so if he deletes the document I want every other user to get updated the document has been removed and remove the document from the listView, it's more like a Food Ordering app so the user order could be taking by another Driver so the document will no longer be available for other users, I want to update the recyclerView Whenever a user deletes a document, so how to get the position without clicking how to detect that change to get the position, Sorry if I couldn't explain much I'm Using Groupie Adapter
val ref = firestore.collection("orders").whereNotEqualTo("userUid", uid)
val adapter = GroupAdapter<GroupieViewHolder>()
ref.addSnapshotListener { value, error ->
if (error != null){
return#addSnapshotListener
}
value?.documentChanges?.forEach {
if (it.type == DocumentChange.Type.ADDED) {
val userUid = it.document.data.get("userUid") as String
val userPhone = it.document.data.get("phone") as String
val userName = it.document.data.get("name") as String
val time = it.document.data.get("time") as String
val marketName = it.document.data.get("marketName") as String
val amount = it.document.data.get("amount") as String
val storeimgUrl = it.document.data.get("storeImg") as String
val order = it.document.data.get("order") as String
val userImg = it.document.data.get("userImg") as String
adapter.add(DriverOrders(userUid, userPhone, userName, time, marketName, amount, storeimgUrl, order, userImg))
adapter.notifyDataSetChanged()
}
if(it.type == DocumentChange.Type.REMOVED){
// here Wher I'm trying to get the position of deleted Or removed data
if (it.document.id == DriverOrders.docId){
adapter.notifyItemRemoved(it.oldIndex)
}
}
}
recyclerview_driverorders.adapter = adapter
}
class DriverOrders(val userUid: String, val userPhone: String,
val userName: String, val time: String,
val marketName: String, val amount: String, val storeimgUrl: String, val order: String,
val userImg: String):Item<GroupieViewHolder>() {
override fun getLayout(): Int {
return R.layout.driver_row
}
override fun bind(viewHolder: GroupieViewHolder, position: Int) {
viewHolder.itemView.driverorders_sName.text = marketName
viewHolder.itemView.driverorders_order.text = order
viewHolder.itemView.driverorders_time.text = Date
Picasso.get().load(storeimgUrl).fit().into(viewHolder.itemView.driverorders_sImg)
}
}
I'm Struggling how to send POST with json using Retrofit2.
like this:
{
"user_available_id": 702,
"teacher_id" : 3207,
"schedule" : [{
"event_id" : 47533,
"schedule_time" : "2020-11-30 07:00:00",
"status" :1
},
{
"event_id" : 47532,
"schedule_time" : "2020-11-30 06:30:00",
"status" :1
}]
}
I'm suppose send post like that. And I wonder is it possible to send like that or there is another way. can you kindly tell me if there is another way. btw here's how I try to send it
CreateSchduleAPI.kt
#POST("schedule/student-create")
#Headers("Accept: application/json")
#SerializedName("data")
suspend fun createScheduleSesi2(
#Header("Authorization") token: String?,
#Body createSchedule: String
): Response<ScheduleModel>
And the Model
ScheduleModel.kt
#Parcelize
data class ScheduleModel(
#field:SerializedName("user_available_id")
var userAvailableId: String? = null,
#field:SerializedName("schedule")
var schedule: ArrayList<schedule?>? = null,
#field:SerializedName("teacher_id")
var teacherId: String? = null
) : Parcelable
#Parcelize
data class schedule(
#field:SerializedName("event_id")
var eventId: String? = null,
#field:SerializedName("schedule_time")
var scheduleTime: String? = null,
#field:SerializedName("status")
var status: String? = null
) : Parcelable
First
private suspend fun getMultiSlotJadwal(id: String, date: String) {
jamList.clear()
val networkConfig =
NetworkConfig().getTeacher().getTeacherScheduleAvailability(token, id, date)
if (networkConfig.isSuccessful) {
if (networkConfig.body()!!.availability!!.isEmpty()) {
binding.rvSlot.visibility = View.GONE
Handler(Looper.getMainLooper()).post {
Toast.makeText(
this,
"Jam tidak tersedia",
Toast.LENGTH_SHORT
).show()
}
} else {
for (slot in networkConfig.body()!!.availability!!) {
//convert tanggal start ke millis
val tanggalSlot = slot!!.start!!.toDate().formatTo("yyyy-MM-dd HH:mm")
val tanggalInMillis = convertToMillis(tanggalSlot)
//ambil tanggal sekarang
val myFormat = "yyyy-MM-dd HH:mm" // format tanggal
val calendar = Calendar.getInstance()
val time = calendar.time
val sdf = SimpleDateFormat(myFormat, Locale.getDefault())
val curdate = sdf.format(time) //diconvert ke tanggal local
val curDateinMillis = convertToMillis(curdate) // convert ke millis
val hasilDate = tanggalInMillis - curDateinMillis
val tanggalJam = hasilDate / 3600000 //diubah dari millis ke jam
if (tanggalJam >= 6) {
jamList.add(slot)
val sortJamList = jamList.sortedBy { jamList -> jamList.start }
binding.rvSlot.visibility = View.VISIBLE
binding.rvSlot.adapter = SlotJamAdapter(sortJamList) {
teacher_id = it.teacherId.toString()
scheduleModel.teacherId = teacher_id
scheduleModel.userAvailableId = user_avalaible_id
scheduleItem.scheduleTime = it.start.toString()
scheduleItem.status = "1"
scheduleItem.eventId = it.id.toString()
scheduleList.add(scheduleItem)
scheduleModel.schedule = scheduleList
itemClicked = true
changeBackgroundButtonSesi2()
}
}
}
}
} else {
Handler(Looper.getMainLooper()).post {
Toast.makeText(
this,
"Jam tidak tersedia",
Toast.LENGTH_SHORT
).show()
}
}
}
Second
private suspend fun createSchedule2Sesi() {
val jsonSchedule = Gson().toJson(scheduleModel)
val networkConfig = NetworkConfig().createSchedule().createScheduleSesi2(
token,
jsonSchedule
)
try {
if (networkConfig.isSuccessful) {
Handler(Looper.getMainLooper()).post {
Toast.makeText(
this,
"Pembuatan Jadwal Berhasil",
Toast.LENGTH_LONG
).show()
startActivity(Intent(this, MainActivity::class.java))
finish()
}
} else {
Handler(Looper.getMainLooper()).post {
Toast.makeText(
this,
"Pembuatan Jadwal Gagal, Cek Koneksi",
Toast.LENGTH_LONG
).show()
}
}
}catch (e:Exception){
Log.e(TAG, "createSchedule2Sesi: ${e.message}", )
}
}
Thank you in advance
Retrofit allows you to use your Kotlin object as a parameter of a call. It will take care of the json serialisation itself if you use GsonConverterFactory when building your Retrofit instance.
That will allow you to change the definition of your endpoint as below
#POST("schedule/student-create")
suspend fun createScheduleSesi2(
#Header("Authorization") token: String?,
#Body createSchedule: ScheduleModel
): Response<ScheduleModel>
I am trying to parse following JSON using moshi but I am unable to dynamic data like USA or UK. USA and UK are dynamic keys.
{
"USA": {
"name": "United State of America",
"code": "US"
},
"UK": {
"name": "United Kingdom",
"code": "UK"
},
"soft_update": "500",
"hard_update": "500"
}
Data class:
data class ApiAppUpdate(val countryMap: Map<String, ApiCountry>,
#field:Json(name = "hard_update")
val forceUpdateVersion: Int,
#field:Json(name = "soft_update")
val softUpdateVersion: Int)
Following is my json adapter code:
fun getConfig(){
val adapter: JsonAdapter<ApiAppUpdate> = moshi.adapter(ApiAppUpdatee::class.java)
}
I get soft and hard update values but countryMap is always null. I am not sure what's wrong in here. Can someone please help me. Thanks.
The problem is that your model description would match this json and not the one you attached:
{
"countryMap":{
"USA":{
"name":"United State of America",
"code":"US"
},
"UK":{
"name":"United Kingdom",
"code":"UK"
}
},
"soft_update":"500",
"hard_update":"500"
}
In your example "USA" and "UK" are on the same level with "soft_update" and "hard_update".
UPDATE:
This is a working solution:
data class ApiCountry(val name: String, val code: String)
data class ApiAppUpdate(
val countryMap: Map<String, ApiCountry>,
#field:Json(name = "hard_update")
val forceUpdateVersion: Int,
#field:Json(name = "soft_update")
val softUpdateVersion: Int
)
class ApiUpdateAdapter {
#FromJson
fun fromJson(reader: JsonReader): ApiAppUpdate {
var forceUpdateVersion: Int = -1
var softUpdateVersion: Int = -1
val map: MutableMap<String, ApiCountry> = mutableMapOf()
reader.beginObject()
while (reader.hasNext()) {
when (reader.peek()) {
JsonReader.Token.NAME ->
when (val fieldName = reader.nextName()) {
"hard_update" -> forceUpdateVersion = reader.nextInt()
"soft_update" -> softUpdateVersion = reader.nextInt()
else -> {
reader.beginObject()
var name = ""
var code = ""
while (reader.hasNext()) {
when (reader.nextName()) {
"name" -> name = reader.nextString()
"code" -> code = reader.nextString()
else -> reader.skipValue()
}
}
reader.endObject()
map[fieldName] = ApiCountry(name, code)
}
}
else -> reader.skipValue()
}
}
reader.endObject()
return ApiAppUpdate(map, forceUpdateVersion, softUpdateVersion)
}
}
fun main() {
val sourceJson =
"{\"USA\":{\"name\":\"United States of America\",\"code\":\"US\"},\"UK\":{\"name\":\"United Kingdom\",\"code\":\"UK\"}" +
",\"soft_update\":\"200\",\"hard_update\":\"300\"}"
val adapter = Moshi.Builder()
.add(ApiUpdateAdapter())
.build()
.adapter(ApiAppUpdate::class.java)
val apiAppUpdate = adapter.fromJson(sourceJson)
println(apiAppUpdate)
}
I have some problem when I try to save array data from an Android Kotlin to Firebase Database.
I want to save data as shown below:
Image 1
but, when I saved the data, in the Firebase database it always updated the "pemasukan" object, not creating new data.
the stored data is always like the picture below
Image 2
Anyone can help me please.
Sorry for my English ;)
This is the code I am using for
class PemasukanActivity : AppCompatActivity() {
private lateinit var database : FirebaseDatabase
private lateinit var mRef : DatabaseReference
lateinit var currentDate : String
private val id_user = "agus"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pemasukan)
btnSimpan()
}
//aksi tombol untuk simpan data
private fun btnSimpan(){
btn_simpan_pemasukan.setOnClickListener {
val pemasukan = Pemasukan()
if (edt_nama_barang.length() > 3){
pemasukan.keterangan = edt_nama_barang.text.toString()
} else {
edt_nama_barang.error ="Nama Barang Harus lebih dari 3 huruf"
return#setOnClickListener
}
if (edt_jumlah.length() > 3){
var jumlah = edt_jumlah.text.toString()
pemasukan.jumlah = jumlah.toLong()
}else{
edt_jumlah.error ="Jumlah Harus lebih dari 3 huruf"
return#setOnClickListener
}
simpanData(pemasukan)
}
}
//simpan data ke firebase
private fun simpanData(listPemasukan :Pemasukan){
val sdf = SimpleDateFormat("ddMyyyy")
currentDate = sdf.format(Date())
val data = Dataitem()
data.id = currentDate
data.user_id = id_user
val nameList = ArrayList<Pemasukan>(Arrays.asList(listPemasukan))
data.pemasukan = nameList
database = FirebaseDatabase.getInstance()
mRef = database.getReference("pendataan")
mRef.child("${currentDate}").setValue(data)
.addOnSuccessListener {
Toast.makeText(this, "Success . .", Toast.LENGTH_LONG).show()
edt_nama_barang.text.clear()
edt_jumlah.text.clear()
}
.addOnFailureListener {
Toast.makeText(this, "Gagal Input Data", Toast.LENGTH_LONG).show()
it.printStackTrace()
Log.e("FIREBASE_ERROR", it.message)
}
}
And the POJO class like this:
data class Dataitem (
var id : String = "",
var user_id : String = "",
var pemasukan : ArrayList<Pemasukan>? = null,
var pengeluaran : ArrayList<Pengeluaran>? = null
)
data class Pengeluaran (var jumlah : Long = 0,
var keterangan : String = "")
data class Pemasukan (var jumlah : Long = 0,
var keterangan : String ="")
Good day, i'm stuck figuring out how to get a single object from a list, i did google but all the topics show how to return a List with sorted objects or something similar.
I have a User Class
class User() {
var email: String = ""
var firstname: String = ""
var lastname: String = ""
var password: String = ""
var image: String = ""
var userId: String = ""
constructor(email:String,
firstname: String,
lastname: String,
password: String,
image: String, userId : String) : this() {
this.email = email
this.firstname = firstname
this.lastname = lastname
this.password = password
this.image = image
this.userId = userId
}
}
In java i would write something like
User getUserById(String id) {
User user = null;
for(int i = 0; i < myList.size;i++;) {
if(id == myList.get(i).getUserId())
user = myList.get(i)
}
return user;
}
How can i achieve the same result in kotlin?
You can do this with find, which gives you the first element of a list that matches a given predicate (or null, if none matched):
val user: User? = myList.find { it.userId == id }
Or if you really do need the last element that matches the predicate, as your Java example code does, you can use last:
val user: User? = myList.last { it.userId == id }
Simplify
val user: User = myList.single { it.userId == id }
or if may list not have your filter
val user: User? = myList.singleOrNull{ it.userId == id }
If you don't want to deal with null objects, try this:
val index = myList.indexOfFirst { it.userId == id } // -1 if not found
if (index >= 0) {
val user = myList[index]
// do something with user
}
You can use this extension function also which return pair Pair(Boolean,T)
e.g
val id=2
val item= myList.customContains{it-> it.userId ==id}
if(item.first){
item.second //your object
// your code here
}else{
// if item no present
}
fun <E> List<E>.customContains(function: (currentItem: E) -> Boolean): Pair<Boolean, E?> {
for (current in 0 until this.size) {
if (function(this[current])) {
return Pair(true, this[current])
}
}
return Pair(false, null)
}