How query firebase database and retrieve specific data - kotlin

If I query database child Readings, I have all items, but if I add a condition, I don't have results.
Someone can help me make the query in order to get all the elements that have the value "2020-9-23" (this will be chosen by the user)?
Thank you
mDatabase!!.child("Readings").child("dia").equalTo("2020-9-23").orderByValue().addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val data: ArrayList<EnergyReading> = ArrayList()
if (dataSnapshot != null) {
for (snapshot: DataSnapshot in dataSnapshot.children) {
try {
data.add(EnergyReading(snapshot.child("reading")))
} catch (e: Exception) {
e.printStackTrace()
}
}
mReadingList = data
Log.i("ReadingModel","data updated there are " + mReadingList!!.size + " Reading in the list")
} else {
throw Exception("data snapshot is null line 31")
}
}

Since the dia property is under reading, you need to order on reading/dia:
mDatabase!!.child("Readings").orderByChild("reading/dia").equalTo("2020-9-23").addListenerForSingleValueEvent(object : ValueEventListener {

Related

Ktorm Repository without duplications

I am creating the repository layer using Ktorm, so far I only have insert and update functions.
override fun create(
entity: ObjectEntity
): Either<DatabaseError, Entity> = try {
val id = database.insertAndGenerateKey(TableName) {
set(TableName.createdTimestamp, entity.createdTimestamp)
set(TableName.updatedTimestamp, entity.updatedTimestamp)
set(TableName.status, entity.status.id)
....
} as Int
entity.id = id
Either.Right(entity)
} catch (e: Exception) {
logger.error(e) {
...
}
Either.Left(DatabaseError(e.message))
}
override fun update(
entity: ObjectEntity
): Either<DatabaseError, Entity> = try {
val effectedRowCount = database.update(TableName) {
set(TableName.updatedTimestamp, entity.updatedTimestamp)
set(TableName.status, entity.status.id)
...
where { it.csmUUID eq entity.csmUUID }
}
if (effectedRowCount < 0) {
Either.Left(MissingEntityError(Entity::class.java, "csmUUID"))
} else {
Either.Right(entity)
}
} catch (e: Exception) {
logger.error(e) {
....
}
Either.Left(DatabaseError(e.message))
}
This code block works like a charm with no issues. But the thing is, there are a lot of fields (more than 20) that are being set in both functions. This causes a code duplication and because of this I can't pass the code quality gate and merge it. Also, I don't like having this much duplicate code. Any suggestions to prevent code duplication in a scenario like this?

How to make callback/coroutines in Method Channel in Kotlin?

I'm trying to make callback to return data by method channel (because I will get the data after another function will activate), but returning variable is already callback.
What should I do?
Kotlin MethodChannel code:
val list: MutableList<String> = ArrayList1()
override fun configureFlutterEngine(#NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call: MethodCall, result: Result? ->
pendingResult = result
if (call.method == "createChannel") {
//**my code**
} else if (call.method == "loginChannel") {
if (userLogged == false) {
//**this is what I want to put in callback**
result?.success(list.toString())
Toast.makeText(this, list.toString(), Toast.LENGTH_LONG).show()
}
}
}
}

.equals function returns false when used to compare 2 livedata objects

I have 2 mutable live data objects
val networkResponse = MutableLiveData<String>()
val initialResponse = MutableLiveData<String>()
In my initial function I give them the the same values from the exact same variable:
fun initialResponser() = viewModelScope.launch {
val valueVariable = try {
db.collection("room1").get().await().size().toString()
} catch(e: Exception) {
Log.d("TAG", "Error getting documents: ", e)
return#launch
}
initialResponse.value=(valueVariable)
networkResponse.value =(valueVariable)
}
In the second, I do the exact same operation, without any changes from the database or any other side:
fun check() = viewModelScope.launch {
val valueVariable = try {
db.collection("room1").get().await().size().toString()
} catch(e: Exception) {
Log.d("TAG", "Error getting documents: ", e)
return#launch
}
networkResponse.value = (valueVariable)
if (initialResponse.toString().equals(valueVariable)){
Log.d(TAG,"đź‘ŤEquals")
}else{
Log.d(TAG,"đź‘ŽNot Equal")
Log.d(TAG, initialResponse.toString().equals(valueVariable).toString())
Log.d(TAG,"Initial Value: ${initialResponse.value}")
Log.d(TAG,"New Value: ${networkResponse.value}")
}
}
The result for check() in the Log is as follows:
D/TAG: đź‘ŽNot Equal
D/TAG: false
D/TAG: 10
D/TAG: 10
When both the values are same where an I going wrong?
The values contained within LiveData objects can be accessed using liveData.value, so if you want to compare their values you have to write
initialResponse.value.equals(valueVariable.value)
In your code when you write initialResponse.toString this essentially returns something like androidx.lifecycle.MutableLiveData#aaa84ba and not the value 10 which you seem to expect

How to retrieve data from Firestore that stored as an Array and set them as EditText values in Kotlin?

I have stored some data as an array in Firestore using the following code. Now, I want to get those values and put them one by one into the EditTexts. How can I do that?
private fun addZipToFirebase() {
val zipList = createListOfZipCodes()
mFireStore.collection(Constants.USERS)
.document(FirestoreClass().getCurrentUserID())
.update("zip_codes", zipList)
.addOnSuccessListener {
Toast.makeText(
this#AssignZIPCodeActivity,
"Zip Codes updates successfully",
Toast.LENGTH_SHORT
).show()
}
.addOnFailureListener { exception ->
Log.e(
javaClass.simpleName,
exception.message,
exception
)
}
}
Edit:
I am trying with the following code to get the data. I want each Zip Code under the field name zip_codes (in the screenshot), in each EditText (etPinCodeOne, etPinCodeTwo, etPinCodeThree and so on). But with following code what I am getting is all the zip codes together in the EditText. Exctely like, [123456, 789456, 132645,798654, 798654, 799865, 764997, 497646, 946529, 946585]. I want each codes in each EditText.
private fun getZipCodesFromFirebase() {
mFireStore.collection(Constants.USERS)
.document(FirestoreClass().getCurrentUserID())
.get()
.addOnSuccessListener { document ->
val list: ArrayList<String> = ArrayList()
list.add(document["zip_codes"].toString())
Toast.makeText(this#AssignZIPCodeActivity,list.toString(),Toast.LENGTH_SHORT).show()
binding.etZipCodeOne.setText(list[0])
}
}
Can someone help me with this please?
To be able to get the zip_codes array, you need to have inside your User class, a property called zip_codes that needs to be declared of type List:
val zip_codes: List<String>
Now, to get it accordingly, please use the following lines of code:
val uid = FirebaseAuth.getInstance().currentUser!!.uid
val rootRef = FirebaseFirestore.getInstance()
val usersRef = rootRef.collection("users")
val uidRef = usersRef.document(uid)
uidRef.get().addOnCompleteListener { task ->
if (task.isSuccessful) {
val document = task.result
if (document.exists()) {
val zip_codes = document.toObject(User::class.java).zip_codes
//Do what you need to do with your list
} else {
Log.d(TAG, "No such document")
}
} else {
Log.d(TAG, "get failed with ", task.exception)
}
}
Since you are getting multiple zip codes, you should consider using a ListView, or even better a RecyclerView, rather than EditTexts.

Kotlin KCallable illegalArgumentException

I have the following Kotlin function:
fun invokeSync(typedArguments : List<Any?>): Any?{
var returnedValue : Any?
try {
returnedValue = callable.call(this, typedArguments);
} catch (e:Exception) {
logInvocationError(e, typedArguments);
throw IllegalArgumentException(e);
}
}
It doesn't matter how much arguments are in this list, I will always get an IllegalArgumentException saying "Callable expects 3 arguments, but 1 were provided".
The function is a simple isGreater-function with 2 arguments of type Int.
I have checked the list of arguments and there are 2 arguments of type Int in there.
Here the function in context:
open class TypedJavaScriptFunction(name: String) : SelfRegisteringJavascriptFunction(MessageFormat.format(JS_NAME_CONVENTION, name)) {
val callable = getCallable(this::class)
override fun function(arguments: Array<Any?>): Any? {
try {
val typedArguments = getTypedArguments(arguments)
val annotations = callable.annotations
for (a in annotations) {
if (a is BrowserFunction) {
if (a.value == Policy.ASYNC) {
invokeAsync(typedArguments);
return null
} else {
return invokeSync(typedArguments)
}
}
}
} catch (e: IllegalArgumentException) {
// this Exception is only for signaling the error; it has already
// been logged before
JavaScriptAPI.showError(browser, "Internal Error (" + callable.name + ")");
}
return null
}
fun getTypedArguments(arguments: Array<Any?>): List<Any?> {
var typedArguments = mutableListOf<Any?>()
val argTypes = callable.valueParameters
if (arguments.size != argTypes.size) {
LOG.error(getName()
+ ": given arguments don't match signature. Given: "
+ arguments.size + ", expected: " + argTypes.size);
throw IllegalArgumentException()
}
for (i in 0 until arguments.size) {
typedArguments.add(TypeRefinery.refine(arguments[i], argTypes[i].type.classifier as KClass<Any>))
}
return typedArguments
}
// ...
fun invokeSync(typedArguments: List<Any?>): Any? {
var returnedValue: Any?
try {
returnedValue = callable.call(this, typedArguments);
} catch (e: Exception) {
logInvocationError(e, typedArguments);
throw IllegalArgumentException(e);
}
// ...
}
}
Did anyone can help me and tell me whats wrong or can give me a hint?
Since call takes a vararg you need to use the spread operator * and toTypedArray() to pass in the List like that:
returnedValue = callable.call(this, *typedArguments.toTypedArray());
The first argument is the instance you are calling the function on and the other two parameters come from the spreaded List, under the condition that List has exactly two elements.