Get Database Row with Anko - android

I have a Kolin Android Application with a Database. I use the Anko library for the Database Communication. I can insert Data in my Database but I have some troubles when I try to get a data row from my Database.
I try to get the Data Row through the following code
try {
var result = select("projects").where("rowid = {id}",
"id" to 1).parseList(StringParser)
Toast.makeText(applicationContext,result.toString(),Toast.LENGTH_LONG).show()
} catch(e: Exception) {
Toast.makeText(applicationContext,e.toString(),Toast.LENGTH_LONG).show()
}
How can I get the content of the Row with the given id
At the moment I get this error
Invalid row: row for SingleColumnParser must contain exactly one column

example :
data class Controler(val id: Int, var name: String, val ssid: String,val password: String,val serialnumber: String): Serializable {}
and in your activity ->
select("projects", "id", "name", "ssid", "password", "serialnumber")
.whereArgs("(id = {controlerId}) ", "controlerId" to id)
.parseOpt(object : MapRowParser<Controler> {
override fun parseRow(columns: Map<String, Any?>): Controler {
controler = Controler(columns.getValue("id").toString().toInt(),
columns.getValue("name").toString(),
columns.getValue("ssid").toString(),
columns.getValue("password").toString(),
columns.getValue("serialnumber").toString())
return controler as Controler
}
})

Hi you must share the complete code, and the log, what message show?
Try this. Why don't use "_id" ? Sqlite required.
select("projects")
.where("(_id = {id}),
"id" to 1)

Related

Unable to Insert values in Room Database in Android [Kotlin]

I am trying to insert values inside my room database but the App Inspection is showing nothing. I have a complex app structure with lot of tables and one database. I am able to perform CRUD operations on all of the tables except for one. I am not able to identify what I am doing wrong.
Code -->
Entity
#Entity(tableName = "add_time")
data class TimeEntity(
#PrimaryKey(autoGenerate = true)
var id: Int? = null,
#ColumnInfo(name = "start_time")
var startTime: String? = "",
#ColumnInfo(name = "end_time")
var endTime: String? = "",
#ColumnInfo(name = "running_time")
var runningTime: String? = "",
)
DAO
#Dao
interface FloorTimeDao {
//Insert time
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertTimeForScheduling(timeEntity: TimeEntity) {
}
}
REPOSITORY
class AddTimeRepository(private val timeDao: FloorTimeDao) {
//insert
#WorkerThread
suspend fun insertTime(time: TimeEntity) = timeDao.insertTimeForScheduling(time)
}
VIEWMODEL
class AddTimeViewModel(private val repository: AddTimeRepository) : ViewModel() {
//insert
fun insertTime(timeEntity: TimeEntity) = viewModelScope.launch {
repository.insertTime(timeEntity)
}
}
VIEWMODEL FACTORY
#Suppress("UNCHECKED_CAST")
class AddTimeViewModelFactory(private val repository: AddTimeRepository) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
if (modelClass.isAssignableFrom(AddTimeViewModel::class.java)) {
return AddTimeViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel Class")
}
}
CODE INSIDE FRAGMENT FOR ADDING VALUE
//Inserting new time in the table
binding.btnAddTime.setOnClickListener {
try {
timeRunning = timeEnd - timeStart
timeRunning = abs(timeRunning)
Timber.d("Final Time start : $timeStart")
Timber.d("Final Time end : $timeEnd")
Timber.d("Final Time running : $timeRunning")
val timeEntity = TimeEntity(
startTime = timeStart.toString(),
endTime = timeEnd.toString(),
runningTime = timeRunning.toString()
)
Timber.d("Time Entity: $timeEntity")
addTimeViewModel.insertTime(timeEntity)
} catch (e: Exception) {
Timber.d("Exception : $e")
}
}
Everything seems to be added correctly and I still cannot seem to find out what I am doing wrong here. Any help would be appreciated. If you need more code I can provide just let me know.
NOTE: With this code basically I am trying to store the time in room database which is taken from the user using Time Picker Dialog.
Edit 1: Found something which I don't know if it is related to the issue or anything. But for the tables in which I am able to insert and read the data the function says something like this :
and for the table (TimeEntity) the function says this :
The difference is that (for the one in which it is working) the functions says Choose Implementation and have a green symbol on left side. But for the table for which it is not working the function says Choose overridden method.
Update: I was able to fix the issue by creating a new Dao Interface for the table. I am still not very sure what might have been the issue as both DAO files looks same. But I have some doubt that it might be due to the room automatic implementations when we create new DAO's or table.
#PrimaryKey(autoGenerate = true)
var id: Int? = null,
Try to change id Int? - To non nullable type Int or Long.
Why do you need to have predefined (initialized) values in entity constructor?
I was able to fix the issue by creating a new Dao file with same functions. The issue may have been due to the automatic implementation of DAO's provided by Room Library.

get the value of a parameter from a data class in kotlin

So, i'm pretty new to kotlin and still learning stuff, I have a data class named Country with 4 parameters
County(name:String, policePhone:String, ambulancePhone:String,
firebrigadePhone:String)
, a listOf Country with 27 objects in it and a var nameC1 taken from the MainActivity.
I've called the list method forEach and I want to confront every name in the list with the variable nameC and when a match is found execute some code.
data class Country(val name: String, val police:String, val ambulance:String,val firefighter:String) {
}
var nameC1 = (activity as MainActivity).nameC
val numberList= listOf<Country>(
Country("Austria","133","144","122"),
Country("Belgium","101","100","100"),
Country("Bulgaria","166","150","160"),
Country("Croatia","192","194","193"),
Country("Cyprus","199","199","199"),
Country("Czech Republic","158","155","150"),
Country("Denmark","112","112","112"),
Country("Estonia","112","112","112"),
Country("Finland","112","112","112"),
Country("France","17","15","18"),
Country("Germany","110","112","112"),
Country("Greece","100","166","199"),
Country("Hungary","107","104","105"),
Country("Ireland","112","112","112"),
Country("Italy","113","118","115"),
Country("Latvia","112","112","112"),
Country("Lithuania","02","03","01"),
Country("Luxembourg","113","112","112"),
Country("Malta","112","112","112"),
Country("Netherlands","112","112","112"),
Country("Poland","997","999","998"),
Country("Portugal","112","112","112"),
Country("Romania","112","112","112"),
Country("Slovakia","158","155","150"),
Country("Slovenia","113","112","112"),
Country("Spain","092","061","080"),
Country("Sweden","112","112","112")
)
numberList.forEach { if (Country.name==nameC1 ) }
// i'm expecting String1==String2 but i'm
//stuck here because it says name is an unresolved reference
}
I'd use a getName() but i know in kotlin getter/setter are automated ( I'm not used to it) and ihaven't found anything useful on the kotlin doc. site,
I've seen on this site that someone suggested to implement Kotlin-reflection but I don't understand how I'm not supposed to get a parameter from a class by default.
forEach creates a lambda for each of the element in the collection. The default name for the element inside the lambda is it. But you can rename it to something else too. Refer to the doc
Here is a working example of your code
data class Country(val name: String, val police:String, val ambulance:String,val firefighter:String)
fun doThis(nameC1: String) {
val numberList= listOf<Country>(
Country("Austria","133","144","122"),
Country("Belgium","101","100","100"),
Country("Bulgaria","166","150","160"),
Country("Croatia","192","194","193"),
Country("Cyprus","199","199","199"),
Country("Czech Republic","158","155","150"),
Country("Denmark","112","112","112"),
Country("Estonia","112","112","112"),
Country("Finland","112","112","112"),
Country("France","17","15","18"),
Country("Germany","110","112","112"),
Country("Greece","100","166","199"),
Country("Hungary","107","104","105"),
Country("Ireland","112","112","112"),
Country("Italy","113","118","115"),
Country("Latvia","112","112","112"),
Country("Lithuania","02","03","01"),
Country("Luxembourg","113","112","112"),
Country("Malta","112","112","112"),
Country("Netherlands","112","112","112"),
Country("Poland","997","999","998"),
Country("Portugal","112","112","112"),
Country("Romania","112","112","112"),
Country("Slovakia","158","155","150"),
Country("Slovenia","113","112","112"),
Country("Spain","092","061","080"),
Country("Sweden","112","112","112") )
numberList.forEach {
if (it.name == nameC1) {
println("Match")
}
}
}
fun main() {
doThis("Slovenia")
}
Try it for yourself on play.kotlinlang.org - Link
The above code will execute the println function when the condition is true.
In the forEach loop you have to use it to access the name parameter.
like this
numberList.forEach { if (it.name==nameC1 )}
Try with the following code. You can apply filter on list
//if you want iterate your list try with below code
numberList.forEach {
val name = it.name
val police = it.police
}
//If you want apply filter on list take reference from below code
private var countryList: ArrayList<Country> = arrayListOf(
Country("Austria", "133", "144", "122"),
Country("Belgium", "101", "100", "100")
)
val searchList = countryList.filter { country-> country.name == nameC1}

Can't convert String to data class objects - Firebase realtime database [duplicate]

This question already has an answer here:
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type Data class object KOTLIN
(1 answer)
Closed 1 year ago.
I have read other comments on this same issue, but none of them has touched on a situation like mine
In mine, below describes how the data is structured:
{
"symbols":{
"alphabets":{
"a":{
"available":true,
"text":"A",
"timestamp":1.512686825309134E9
},
"b":{
"available":true,
"text":"B",
"timestamp":1.512687248764272E9
}"NameOfSymbols":"alphabets"
}
}
}
*The reason why mine is showing the error is that it can't convert the string "NameOfSymbols" : "alphabets" to the objects as specified in the data class
So, what can be done about it, I use Kotlin
Is there a way I can exclude that part of the children value while I only get the one that is specified in the data class?
Data Class
data class alphabets(
val name: Names,
var NameOfSymbols: String? = null) {
data class Names(
var available: Boolean? = null,
var text: String? = null,
var timestamp: Long? = null) {
}
}
This structure might work for your case (untested):
data class Message(
#PropertyName("symbols") val symbols: Symbols,
)
data class Symbols(
#PropertyName("alphabets") val alphabets: Alphabets,
)
data class Alphabets(
#PropertyName("a") val a: Alphabet,
#PropertyName("b") val b: Alphabet,
#PropertyName("NameOfSymbols") val nameOfSymbols: String,
)
data class Alphabet(
#PropertyName("available") val available: Boolean,
#PropertyName("text") val text: String,
#PropertyName("timestamp") val timestamp: Long,
)
Usage would be:
// in your ValueEventListener
override fun onDataChange(snapshot: DataSnapshot) {
val value = snapshot.getValue<Message>()
}
If you want to exclude your NameOfSymbols, you should remove it, and add the #IgnoreExtraProperties, like shown below:
#IgnoreExtraProperties
data class Alphabets(
#PropertyName("a") val a: Alphabet,
#PropertyName("b") val b: Alphabet,
)
NOTE, I used these versions of firebase database:
implementation 'com.google.firebase:firebase-database:19.7.0'
implementation 'com.google.firebase:firebase-database-ktx:19.7.0'
ok, After reading the documentation on Structuring Database on the firebase docs website, Structure your database
I realised that i didn't structure my database well, i should have regrouped them after specifying the name
like below
{
// This is a poorly nested data architecture, because iterating the children
// of the "chats" node to get a list of conversation titles requires
// potentially downloading hundreds of megabytes of messages
"chats": {
"one": {
"title": "Historical Tech Pioneers",
"messages": {
"m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
"m2": { ... },
// a very long list of messages
}
},
"two": { ... }
}
}
Although, it said that structuring it that way isn't a nice way, it seems that's what works for me

endAt() with limitToLast() in Firebase query is not working as expected in android

I am using the firebase real-time database to store chat messages schema is like below
"chat_message" : {
"up-29709425-fef2-490c-8335-77dbeafbce1e" : {
"-MLhPH_i7bfvnTpccK1k" : {
"chat_room_id" : "up-29709425-fef2-490c-8335-77dbeafbce1e",
"created_at" : "2020-11-09T19:59:11+05:30",
"creator_id" : 15456623,
"message" : "hii",
"message_type" : "text",
"time_in_ms" : 1604932151865
}
},
"up-299bcd2f-90bb-4ca2-b526-7e858d2d98fe" : {
"-MLhWydTKmB52W_XFtS6" : {
"chat_room_id" : "up-299bcd2f-90bb-4ca2-b526-7e858d2d98fe",
"created_at" : "2020-11-09T20:32:47+05:30",
"creator_id" : 15451746,
"message" : "hoi",
"message_type" : "text",
"time_in_ms" : 1604934167159
}
}
The problem is for the first time, I am getting 10 items and after that, I am not able to get the next 10 items. Here are the queries I am using
private var query: Query? = null
private fun getInitialChatMessages(time: String?, key: String?) {
query = if (time == null) {
// For first time I am getting last 10 items
getFirebaseDbReference()
.child(FIREBASE_DATABASE_LOCATION_MESSAGES)
.child(project?.userProjectId!!)
.orderByChild("time_in_ms")
.limitToLast(INITIAL_FETCH_MESSAGE_COUNT)
} else {
// on scroll its not working
getFirebaseDbReference()
.child(FIREBASE_DATABASE_LOCATION_MESSAGES)
.child(project?.userProjectId!!)
.orderByChild("time_in_ms")
.endAt("$time")
.limitToLast(INITIAL_FETCH_MESSAGE_COUNT)
}
query?.addListenerForSingleValueEvent(listener)
}
Any help would be appreciated. Thanks in advance.
The time property in your database is a numeric value, but in your code you're passing it as a string. When the database compares a number and a string, they are never the same.
So you'll want to fix your code so that is also treats the time as a number, or at the very least pass is as a number to the database by calling toDouble() on it.

How to create kotlin data class for this network service?

I want to know what approach you will take to make data class in this situation, In this JSON service
I have subCategories under the other-services field. every item in the subCategories has a slug field which is also one of the field in other data elements like - digital-currency, picture, print. now my requirement is I want to pick up appropriate data class based on user selection of subCategories item. if the user has selected below item
{
"title": "電子マネー",
"slug": "digital-currency"
}
then I should be able to match the slug field and then should pick up the digital-currency data element
"digital-currency": {
"slug": "digital-currency",
"title": "電子マネー",
"_id": "7j6OzPKVzim7xvW8BvI8zV",
"isSub": true,
"parent": "other-services"
}
how can I make data class for this ?
You could simplify your code by..
data class NetworkResponse(
val otherServices: OtherServices,
val digitalCurrency: SubCategory,
val picture: SubCategory,
val print: SubCategory
) {
fun getUserSelectedCategory(slug : String) : SubCategory? {
return when (slug) {
"digital-currency" -> digitalCurrency
"picture" -> picture
"print" -> print
else -> null
}
}
}
data class OtherServices(val subCategory: List<SubCategory>)
data class SubCategory(val title: String, val slug: String)
Below is my solution , If I understand it properly , it is nothing but finding object of given type in a heterogeneous List. here DigitalCurrency, Picture, Print, pet-supplies,... so on , are all heterogeneous type. To pick any one of this item , you uses slug field as identifier, you must have mapping mechanism to pick right data object for given type with given json structure.
however solution of mine goes adding WHEN condition every time when new data element added at backend. I believe , as per the requirement and Json structure made here , this cannot be generalize to any extend where It can map to appropriate data class without any additional changes in Code in future.
if you think that Data class can be construct in such way that it doesn‘t need any change in code to accommodate newly added data , Please let me know.
data class NetworkResponse(
val otherServices: OtherServices,
val digitalCurrency: DigitalCurrency,
val picture: Picture,
val print: Print
) {
fun getUserSelectedCategory(slug : String) : BaseClass {
when (slug) {
"digital-currency" -> {
return digitalCurrency
}
"picture" -> {
return picture
}
"print" -> {
return print
}
}
}
}
data class OtherServices(val subCategory: List<SubCategory>) {
}
interface BaseClass
data class SubCategory(val title: String, val slug: String) : BaseClass
data class DigitalCurrency(val title: String, val slug: String) : BaseClass
data class Picture(val title: String, val slug: String) : BaseClass
data class Print(val title: String, val slug: String) : BaseClass

Categories

Resources