I'm trying to create a login app. I want it to do nothing more than either store the account info on a db if the username is not already used. Problem is, no matter what I try, I cannot check if the username is already in the db
I've tried to get both LiveData from my query, as well as String?, as shown below with no success
I have also tried setting an onConflict strategy other than ignore, and then putting my addUser function call in a try-catch block, but it crashes
#Entity(tableName = "Users_table")
data class User(
#PrimaryKey var username: String,
#ColumnInfo var firstName: String,
#ColumnInfo var lastName: String,
#ColumnInfo var email: String,
#ColumnInfo var password: String
)
#Dao
interface UsersDao {
#Insert(onConflict = OnConflictStrategy.IGNORE)
fun addUser(user: User)
#Query("Select username from users_table Where username = :username")
fun getUser(username: String): String?
}
#Database(entities = [User::class], version = 1)
abstract class UsersDatabase: RoomDatabase() {
abstract fun userDao(): UsersDao
companion object{
#Volatile
private var INSTANCE: UsersDatabase? = null
fun getDatabase(context: Context): UsersDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
UsersDatabase::class.java,
"users_database"
).build()
INSTANCE = instance
return instance
}
}
}
}
class UsersRepository(private val usersDao: UsersDao) {
suspend fun addUser(user: User){
usersDao.addUser(user)
}
suspend fun getUser(username: String) {
usersDao.getUser(username)
}
}
class UsersViewModel(application: Application): AndroidViewModel(application) {
//private val getUser: LiveData<List<User>>
private val repository: UsersRepository
init {
val userDao = UsersDatabase.getDatabase(application).userDao()
repository = UsersRepository(userDao)
//getUser = repository.getUser
}
fun addUser(user: User) {
viewModelScope.launch(Dispatchers.IO) {
repository.addUser(user)
}
}
fun getUser(username: String) {
viewModelScope.launch(Dispatchers.IO) {
repository.getUser(username)
}
}
}
...
if (mUsersViewModel.getUser(binding.etRegUsername.text.toString()).toString() != "0") {
Toast.makeText(this, "Username already exists", Toast.LENGTH_SHORT).show()
} else {
mUsersViewModel.addUser(user)
Toast.makeText(this, "User successfully created", Toast.LENGTH_SHORT).show()
}
...
You can use this query to get count of users with given user name
#Query("Select count(*) from users_table Where username LIKE :username")
fun getUser(username: String): Int?
and use this to check if there are user
if (mUsersViewModel.getUser(binding.etRegUsername.text.toString()) != 0) {
Toast.makeText(this, "Username already exists", Toast.LENGTH_SHORT).show()
} else {
mUsersViewModel.addUser(user)
Toast.makeText(this, "User successfully created", Toast.LENGTH_SHORT).show()
}
You have two options:
Fetch all the data first and then compare it with your editText's data(username,email)
Set an query inside the UsersDao , to check whether an entry with same values exists or not.
Related
I am trying to make a function which will check whether this id is already present or not in the database, But it is not working as required.It take the insert value in database.
private fun CheckDuplicateId(id:String,donorDao:DonorDao):Boolean{
var result=true
lifecycleScope.launch {
donorDao.fetchAllDonor().collect(){
var Donorlist=ArrayList(it)
for(item in Donorlist){
if (item.id==id){
result=false
}
}
}
}
return result
}
I am using this function in while inserting the entry
private fun addRecord(donorDao:DonorDao){
val Id:String=binding?.etDonorId?.text.toString()
val bloodGr=binding?.etDonorBloodgroup?.text.toString()
if(Id.isNotEmpty() && bloodGr.isNotEmpty() && CheckDuplicateId(Id,donorDao)){
lifecycleScope.launch {
donorDao.insert(DonorEntity(id = binding?.etDonorId?.text.toString(), bloodGroup = bloodGr))
Toast.makeText(applicationContext, "Record saved", Toast.LENGTH_SHORT).show()
}
}else{
Toast.makeText(this,"duplicate value",Toast.LENGTH_SHORT).show()
}
}
here donor entity
#Entity(tableName = "donor-table")
data class DonorEntity(
#PrimaryKey(autoGenerate = true)
var sr_no:Int=0,
var id:String="",
var bloodGroup:String="")
here donor dao
#Dao
interface DonorDao {
#Insert
suspend fun insert(donorEntity:DonorEntity)
#Update
suspend fun update(donorEntity:DonorEntity)
#Delete
suspend fun delete(donorEntity:DonorEntity)
#Query("SELECT*FROM `donor-table`")
fun fetchAllDonor(): Flow<List<DonorEntity>>
#Query("SELECT*FROM `donor-table` Where id=:id")
fun fetchDonorById(id:Int): Flow<DonorEntity>
}
here the database
#Database(entities = [DonorEntity::class], version = 2)
abstract class DonorDatabase:RoomDatabase() {
abstract fun donorDao():DonorDao
companion object{
#Volatile
private var INSTANCE:DonorDatabase?=null
fun getInstance(context: Context):DonorDatabase{
synchronized(this){
var instance=INSTANCE
if (instance==null){
instance=Room.databaseBuilder(context.applicationContext,
DonorDatabase::class.java,"donor_database")
.fallbackToDestructiveMigration().build()
}
INSTANCE=instance
return instance
}
}
}
}
Your method returning true immediately:
private fun CheckDuplicateId(id:String,donorDao:DonorDao):Boolean{
var result=true
lifecycleScope.launch {
donorDao.fetchAllDonor().collect(){
var Donorlist=ArrayList(it)
for(item in Donorlist){
if (item.id==id){
result=false
}
}
}
}
return result // return true immediately
}
So, do it inside
private fun addRecord(donorDao:DonorDao){
val Id:String=binding?.etDonorId?.text.toString()
val bloodGr=binding?.etDonorBloodgroup?.text.toString()
if(Id.isNotEmpty() && bloodGr.isNotEmpty()){
lifecycleScope.launch {
// check here CheckDuplicateId(Id,donorDao) synchronously
donorDao.insert(DonorEntity(id = binding?.etDonorId?.text.toString(), bloodGroup = bloodGr))
Toast.makeText(applicationContext, "Record saved", Toast.LENGTH_SHORT).show()
}
}else{
Toast.makeText(this,"duplicate value",Toast.LENGTH_SHORT).show()
}
}
One way to do that is at DB level is using index. This will only insert if table as no with same id value. You can avoid select * query which would affect performance if you have many data in you case.
#Entity(tableName = "donor-table",indices = [Index(value = ["id"], unique = true)])
data class DonorEntity(
#PrimaryKey(autoGenerate = true)
var sr_no:Int=0,
#ColumnInfo(name = "id")
var id:String="",
var bloodGroup:String="")
To make certain fields or groups of fields in a database unique, you can enforce this uniqueness property by setting the unique property of an #Index annotation to true.
#Entity(indices = [Index(value = ["first_name", "last_name"],
unique = true)])
data class User(
#PrimaryKey val id: Int,
#ColumnInfo(name = "first_name") val firstName: String?,
#ColumnInfo(name = "last_name") val lastName: String?,
#Ignore var picture: Bitmap?
)
Here is the Official Docs
The following code is an MVVM architecture-based ROOM implementation in Kotlin for Android.
I have a problem with the pre-population of the database. My database doesn't have any data or I can't find the solution to get or insert data.
The IDE doesn't throw any compilation problems.
I think the problem is in the ViewModel but I'm at a dead end.
EDITED: I have seen the DB and it's populated. The insert is fine but not the data read. I will try to modify the ViewModel and its associated livedata and mutablelive data.
This is my data class:
#Entity(tableName = Constants.DATABASE_NAME)
data class Card(
#PrimaryKey(autoGenerate = true) #ColumnInfo(name = Constants.COLUMN_NAME_ID) val id: Int?,
#ColumnInfo(name = Constants.COLUMN_NAME_FAV) val fav: Boolean,
#ColumnInfo(name = Constants.COLUMN_NAME_DATE) val date: Date,
#ColumnInfo(name = Constants.COLUMN_NAME_RAW_VALUE) val rawValue: String,
#ColumnInfo(name = Constants.COLUMN_NAME_STORE_TYPE) val storeType: String,
#ColumnInfo(name = Constants.COLUMN_NAME_STORE_NAME) val storeName: String,
#ColumnInfo(name = Constants.COLUMN_NAME_STORE_NOTES) val storeNotes: String
)
This is my interface dao
#Insert
suspend fun insertNewCard(card: Card) {
}
#Delete
suspend fun deleteCard(card: Card)
#Query("SELECT * FROM ${Constants.DATABASE_NAME}")
fun getAllCards(): LiveData<List<Card>>
UPDATE:
This is my Database class
#Database(
entities = [Card::class],
version = 1,
exportSchema = true,
//autoMigrations = [AutoMigration (from = 1, to = 2)]
)
#TypeConverters(Converters::class)
abstract class CardsDatabase : RoomDatabase() {
abstract fun cardsDao(): CardsDao
private class CardsDatabaseCallback(private val scope: CoroutineScope)
: RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
INSTANCE?.let { database ->
scope.launch {
populateDatabase(database.cardsDao())
}
}
}
suspend fun populateDatabase(cardsDao: CardsDao) {
val testCard = Card(null,
false,
((Calendar.getInstance()).time),
"test",
"codebar test 1",
"Prueba tienda",
"Esta es una tienda de prueba"
)
val testCardTwo = Card(null,
false,
((Calendar.getInstance()).time),
"barcode test 2",
"codebar",
"Prueba tienda 2",
"Esta es una segunda prueba de tienda"
)
Log.d("ROOM", "$testCard")
cardsDao.insertNewCard(testCard)
}
}
companion object {
#Volatile
private var INSTANCE: CardsDatabase? = null
fun getDatabase(context: Context, scope: CoroutineScope): CardsDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
CardsDatabase::class.java,
Constants.DATABASE_NAME)
.addCallback(CardsDatabaseCallback(scope))
.build()
INSTANCE = instance
instance
}
}
}
This is the repository class
val allCards: LiveData<List<Card>> = cardsDao.getAllCards()
#Suppress("RedundantSuspendModifier")
#WorkerThread
suspend fun insertCard(card: Card) {
cardsDao.insertNewCard(card)
}
suspend fun deleteCard(card: Card) {
cardsDao.deleteCard(card)
}
This is my viewModel:
The Logcat shows as null the LiveData at this point.
private val _allCards = MutableLiveData<List<Card>>()
val allCards : LiveData<List<Card>> = _allCards
init {
getAllCards()
Log.d("ROOM", "${allCards.value}")
}
private fun getAllCards() = viewModelScope.launch {
_allCards.value = cardRepository.allCards.value
Log.d("ROOM", "_ : ${_allCards.value}")
}
fun insertCard(card: Card) = viewModelScope.launch {
cardRepository.insertCard(card)
Log.d("ROOM", "inserted: $card")
}
}
class CardsViewModelFactory(private val repository: CardRepository) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(CardsViewModel::class.java)) {
#Suppress("UNCHECKED_CAST")
return CardsViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
This is the application class:
private val applicationScope = CoroutineScope(SupervisorJob())
private val database by lazy { CardsDatabase.getDatabase(this, applicationScope) }
val repository by lazy { CardRepository(database.cardsDao()) }
For last, the observe in MainActivity:
cardsViewModel.allCards.observe(this) { cards ->
cards?.let { adapter.setData(it) }
}
My version.
It works with classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21'
add to build.gradle:
plugins {
id 'kotlin-kapt'
}
dependencies {
def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
testImplementation "androidx.room:room-testing:$room_version"
}
create Entity.class:
#Entity(tableName = "cards")
data class CardEntity(
#PrimaryKey(autoGenerate = true)
val id: Int = 0,
val data: String
)
create Dao.class
#Dao
interface CardDAO {
#Insert
suspend fun insert(cardEntity: CardEntity): Long
#Delete
suspend fun delete(cardEntity: CardEntity): Int
#Update
suspend fun update(cardEntity: CardEntity): Int
#Query("SELECT * FROM cards WHERE id = :id")
fun getDataById(id:Int): Flow<CardEntity?>
#Query("SELECT * FROM cards")
fun getAll(): Flow<List<CardEntity>>
}
create Database.class:
for work you should to use singleton
#Database(
entities = [
CardEntity::class
],
version = 1
)
abstract class MyDatabase : RoomDatabase() {
companion object {
private var INSTANCE: MyDatabase? = null
fun get(context: Context): MyDatabase {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context, MyDatabase::class.java,
"testBase").build()
}
return INSTANCE as MyDatabase
}
}
abstract fun cardDAO(): CardDAO
}
test TestDatabase.class:
#RunWith(AndroidJUnit4::class)
class TestDatabase {
lateinit var db: MyDatabase
#Before
fun createDB() {
val appContext =
InstrumentationRegistry.getInstrumentation().targetContext
db = Room.inMemoryDatabaseBuilder(appContext,
MyDatabase::class.java).build()
}
#After
#Throws(IOException::class)
fun closeDB() {
db.close()
}
private fun setData() = runBlocking {
db.cardDAO().insert(CardEntity(data = "1"))
db.cardDAO().insert(CardEntity(data = "2"))
db.cardDAO().insert(CardEntity(data = "3"))
db.cardDAO().insert(CardEntity(data = "4"))
db.cardDAO().insert(CardEntity(data = "5"))
}
#Test
fun test() = runBlocking {
setData()
Assert.assertEquals(db.cardDAO().getAll().first().size, 5)
val flowIdFirst = db.cardDAO().getDataById(1)
Assert.assertEquals(flowIdFirst.first()?.data, "1")
Assert.assertEquals(db.cardDAO().getDataById(2).first()?.data, "2")
Assert.assertEquals(db.cardDAO().getDataById(3).first()?.data, "3")
Assert.assertEquals(db.cardDAO().getDataById(4).first()?.data, "4")
Assert.assertEquals(db.cardDAO().getDataById(5).first()?.data, "5")
Assert.assertTrue(db.cardDAO().update(CardEntity(1, "my new data")) > 0)
Assert.assertEquals(flowIdFirst.first()?.data, "my new data")
Assert.assertTrue(db.cardDAO().delete(CardEntity(1,"")) > 0)
Assert.assertEquals(flowIdFirst.first(), null)
}
}
The problem is the LiveData created in DAO. To fix it:
Remove LiveData from DAO to return a List:
#Query("SELECT * FROM ${Constants.DATABASE_NAME}")
suspend fun getAllCards(): List<Card>
From the repository, make a suspend fun that gets access to DAO and gets the List, and remove the LiveData type.
suspend fun getAllCards() : List<Card> = cardsDao.getAllCards()
Change the method to access the repository in ViewModel. It works fine.
private fun getAllCards() = viewModelScope.launch {
_allCards.value = cardRepository.getAllCards()
}
Solved.
I am not sure what is exactly happening but when ApiService.apiService.getPokemon(name) in fun getPokemon in PokemonRepository.kt is called then the function getPokemon stops executing and emited livedata are then observed as null in DetailAktivity.kt instead of a valid Pokemon class.
I have checked the API call and it is working in other cases. I am new to Android programming, so I would appreciate some detailed explanation.
Here are the classes:
PokemonRepository.kt
class PokemonRepository(context: Context) {
companion object {
private val TAG = PokemonRepository::class.java.simpleName
}
private val pekemonDao = PokemonDatabase.getInstance(context).pokemonDao()
fun getPokemon(name: String) = liveData {
val disposable = emitSource(
pekemonDao.getOne(name).map {
it
}
)
val pokemon = ApiService.apiService.getPokemon(name)
try {
disposable.dispose()
pekemonDao.insertAllPokemons(pokemon)
pekemonDao.getOne(name).map {
it
}
} catch (e: Exception) {
Log.e(TAG, "Getting data from the Internet failed", e)
pekemonDao.getOne(name).map {
e
}
}
}
DetailActivity.kt
class DetailActivity : AppCompatActivity() {
companion object {
const val ITEM = "item"
}
private lateinit var binding: ActivityDetailBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
val vm: DetailViewModel by viewModels()
vm.pokemon.observe(
this,
{
binding.name.text = it.name
supportActionBar?.apply {
setDisplayShowTitleEnabled(true)
title = it.name
}
}
)
intent.extras?.apply {
vm.setCharacterId(getString(ITEM)!!)
}
}
}
DetailViewModel
class DetailViewModel(application: Application) : AndroidViewModel(application) {
private val repository = PokemonRepository(application)
private val name: MutableLiveData<String> = MutableLiveData()
val pokemon = name.switchMap { name ->
repository.getPokemon(name)
}
fun setCharacterId(characterId: String) {
name.value = characterId
}
}
ApiService.kt
interface ApiService {
#GET("pokemon?offset=0&limit=151")
suspend fun getPokemons(#Query("page") page: Int): NamedApiResourceList
#GET("pokemon/{name}")
suspend fun getPokemon(#Path("name") name: String): Pokemon
companion object {
private const val API_ENDPOINT = "https://pokeapi.co/api/v2/"
val apiService by lazy { create() }
private fun create(): ApiService = Retrofit.Builder()
.baseUrl(API_ENDPOINT)
.addConverterFactory(MoshiConverterFactory.create())
.client(OkHttpClient())
.build()
.create(ApiService::class.java)
}
}
Pokemon data class
#Parcelize
#JsonClass(generateAdapter = true)
#Entity
data class Pokemon(
#PrimaryKey val id: Int,
val name: String,
#ColumnInfo(name = "base_experience") val baseExperience: Int,
val height: Int,
#ColumnInfo(name = "is_default") val isDefault: Boolean,
val order: Int,
val weight: Int,
val sprites: PokemonSprites,
) : Parcelable
PokemonDao.kt
#Dao
interface PokemonDao {
#Query("SELECT * FROM namedapiresource")
fun getAll(): LiveData<List<NamedApiResource>>
#Query("SELECT * FROM pokemon WHERE name=:name")
fun getOne(name: String): LiveData<Pokemon>
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertAllNamedApiResources(vararg characters: NamedApiResource)
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertAllPokemons(vararg characters: Pokemon)
}
I would guess because of how your getPokemon is defined:
val disposable = emitSource(
// Attempts to get a pokemon from the database - presumably this does
// not exist at first so would return null first
pekemonDao.getOne(name).map {
it
}
)
// AFTER NULL IS RETURNED this tries to fetch from the API
val pokemon = ApiService.apiService.getPokemon(name)
try {
disposable.dispose()
pekemonDao.insertAllPokemons(pokemon)
// After fetching from API, finally returns a non-null
pekemonDao.getOne(name).map {
it
}
So maybe just get ride of the initial block?
val disposable = emitSource(
pekemonDao.getOne(name).map {
it
}
)
I do not know how to implement a filter query properly inside the Repository and the ViewModel to use it to display the filtered string in a Textview or anything else really. My Entity, Dao, Repository, and ViewModel are as follows:
User.kt
#Entity(tableName = "user_data")
data class User (
#PrimaryKey(autoGenerate = true) val id: Int,
#ColumnInfo(name = "name") val name: String
)
UserDao.kt
#Dao
interface UserDao {
#Insert
fun addUser(user: User)
#Query("SELECT name FROM user_data WHERE name LIKE :filter LIMIT 1")
fun getFilteredUser(filter: String): LiveData<String>
}
UserRepository.kt
class UserRepository(private val userDao: UserDao) {
fun addUser(user: User) { userDao.addUser(User) }
fun getFilteredUser(filter: String) {userDao.getFilteredUser(filter)}
}
UserViewModel.kt
class UserViewModel(application: Application): AndroidViewModel(application) {
private val repository: UserRepository
init {
val userDao = UserDatabase.getDatabase(application).userDao()
repository = UserRepository(userDao )
}
fun addUser(user: User) {
viewModelScope.launch(Dispatchers.IO){
repository.addUser(user)
}
}
fun getFilteredUser(filter: String){
return repository.getFilteredUser(filter)
}
}
How would I proceed from here to make it possible to e.g. display the filtered User String in a textview or anything like that and how do I write the method correctly inside the repository and the viewmodel?
Thank you for your help!
Try the following
UserDao
change getFilteredUser as follows
#Query("SELECT name FROM user_data WHERE name LIKE '%' || :filter || '%' LIMIT 1")
fun getFilteredUser(filter: String): Stringl̥
UserRepo
use coroutines to perform the database I/O operations
suspend fun addUser(user: User) {
withContext(Dispatchers.IO) {
userDao.addUser(user)
}
}
suspend fun getFilteredUser(filter: String): String {
return withContext(Dispatchers.IO) {
userDao.getFilteredUser(filter)
}
}
ViewModel
fun addUser(user: User) {
viewModelScope.launch {
repository.addUser(user)
}
}
private val _dataToUi = MutableLiveData<String>()
val dataToUi: LiveData<String>
get() = _dataToUi
suspend fun getFilteredUser(filter: String): String? {
return withContext(Dispatchers.IO) {
repository.getFilteredUser(filter)
}
}
// to set the filterquery from the fragment/activity
fun setFliterQuery(query: String) {
viewModelScope.launch {
_dataToUi.value = getFilteredUser(query)
}
}
Activity
binding.button.setOnClickListener {
val queryKey = binding.queryKey.text.toString()
Log.i("activity", queryKey)
userViewModel.setFliterQuery(queryKey)
}
userViewModel.dataToUi.observe(this) { result ->
result?.apply {
Log.i("activity", result)
binding.resultText.text = result
}
}
i am implementing Room with a vIewModel, my structure is the following
#DAO,#Entity,#Database,#Repository
#Entity(tableName="dx_table")
class dx_table(
#ColumnInfo(name = "name")
val naxme: String,
#PrimaryKey
#ColumnInfo(name = "phone")
val phone: String,
#ColumnInfo(name = "passx")
val passx: String,
#ColumnInfo(name = "login_fx")
val login_fx: String
)
#Dao
interface dx_dao{
#Query("SELECT * FROM dx_table")
fun get_all():LiveData<List<dx_table>>
#Insert
suspend fun insertTrx(dx_table:dx_table)
#Query("UPDATE dx_table SET login_fx =:login_fx where phone=:phonex")
suspend fun insertFx(login_fx: String,phonex: String)
#Query("SELECT * from dx_table where phone=:phonex")
suspend fun get_name_px(phonex: String):List<dx_table>
#Query("Delete from dx_table")
suspend fun deleteAll()
#Query("Select * from dx_table where login_fx=1")
suspend fun selectFx():List<dx_table>
}
#Database(entities = arrayOf(dx_table::class), version = 1, exportSchema = false)
public abstract class DxDatabase : RoomDatabase() {
abstract fun dxDao(): dx_dao
companion object {
// Singleton prevents multiple instances of database opening at the
// same time.
#Volatile
private var INSTANCE: DxDatabase? = null
fun getDatabase(context: Context): DxDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
DxDatabase::class.java,
"dx_database"
).build()
INSTANCE = instance
return instance
}
}
}
}
class dxRepository(private val dxDao: dx_dao ){
val k_d:LiveData<List<dx_table>> = dxDao.get_all()
suspend fun insert_trx(dx_table: dx_table){
dxDao.insertTrx(dx_table)
}
suspend fun insert_fx(login_fx: String,phonex: String) {
dxDao.insertFx(login_fx,phonex)
}
suspend fun select_fx() {
dxDao.selectFx()
}
suspend fun get_name_px(phonex: String) :List<dx_table> {
return dxDao.get_name_px(phonex) as List<dx_table>
}
}
The viewmodel is
class DxViewModel (application: Application) : AndroidViewModel(application) {
var repository: dxRepository
var k_d: LiveData<List<dx_table>>
init {
// Gets reference to WordDao from WordRoomDatabase to construct
// the correct WordRepository.
val dxDao = DxDatabase.getDatabase(application).dxDao()
repository = dxRepository(dxDao)
k_d = repository.k_d
}
fun insert_trx(dxTable: dx_table) = viewModelScope.launch {
repository.insert_trx(dxTable)
}
fun insert_fx(login_fx: String, phonex: String) = viewModelScope.launch {
repository.insert_fx(login_fx, phonex)
}
fun select_fx() = viewModelScope.launch {
repository.select_fx()
}
fun get_name_px(phonex: String) = viewModelScope.launch {
repository.get_name_px(phonex)
}
}
I can track the live data using observe,its not an issue, the problem i am facing is with the get_name_px(phone)
var mView = ViewModelProviders.of(this).get(DxViewModel::class.java)
var lm = mView.get_name_px(phone)
here lm seems to be job type , i need the return List , how do i get it .
In your viewModel function select_fx() return a job, because launch does not return result, so you have to either:
1) Use async and await
fun get_name_px(phonex: String) = viewModelScope.async {
repository.get_name_px(phonex)
}.await()
2) Not use launch viewModel, use it in Activity/Fragment
suspend fun get_name_px(phonex: String) = repository.get_name_px(phonex)
class CardFragment : Fragment() {
fun get() {
// launch in Dispatchers.Main
lifecycleScope.launch {
var lm = mView.get_name_px(phone)
}
// launch in background thread
lifecycleScope.launch(Dispatchers.Default) {
var lm = mView.get_name_px(phone)
}
}
}