0

i am new to kotlin android i am trying to use room with flow my code as follows

my entity as follows

@Entity(tableName = "user_data")
data class User (
    @PrimaryKey(autoGenerate = true)
    val id:Int,
    val firstName:String,
    val lastName:String,
    val age:Int)

my database class as follows

@Database(entities = [User::class],version = 1,exportSchema = false)
 abstract class UserDatabase :RoomDatabase(){
     abstract fun userDao():UserDao

     companion object{
         @Volatile
         private var INSTANCE:UserDatabase?=null

         fun getDataBaseInstance(context:Context):UserDatabase
         {
             var tempInstance= INSTANCE
             if(tempInstance!=null)
             {
                 return tempInstance
             }
             synchronized(this)
             {
                 val instance=Room.databaseBuilder(context.applicationContext,UserDatabase::class.java,"user_database")
                                          .build()
             INSTANCE=instance
                return instance
             }
         }
     }
}

my dao as follows

@Dao
interface UserDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun addUser(user:User) :Long

    @Query("SELECT * from user_data")
    fun fetchUserData(): Flow<List<User>>

}

my repository as follows

class UserRepository(private val userDao:UserDao) {


    suspend fun addUser(user:User){
        val rowid:Long=userDao.addUser(user)

    }


    fun readAllUserData():Flow<List<User>>
    {
        val temp=userDao.fetchUserData()
        return temp
    }
}

my view model as follows

class UserViewModel(application: Context) :ViewModel() {
    private lateinit var _readAllData:MutableLiveData<List<User>>
    private  var repository: UserRepository

    private var _firstName:String="Akshay"
    val firstName:String get()=_firstName

    private var _lastName:String=""
    val lastName:String get()=_lastName

    private var _age:String = ""
    val age:String get()=_age


    val readAllData:LiveData<List<User>> get()=_readAllData

    init {
        val userDao= UserDatabase.getDataBaseInstance(application).userDao()
        repository=UserRepository(userDao)

    }

    fun setFirstName(name:String)
    {
        _firstName=name
    }


    fun setLastName(name:String)
    {
        _lastName=name
    }


    fun setAge(name:String)
    {
        _age=name
    }

    fun addUserToDB()
    {
        viewModelScope.launch(Dispatchers.IO) {
           println("Inside addUserDB")
           repository.addUser(User(0,_firstName,_lastName,_age.toInt()))
        }

    }

    fun readDataFromUserTable():LiveData<List<User>>
    {
        return repository.readAllUserData().asLiveData()
    }
}


class UserViewModelFactory(private val context: Context):ViewModelProvider.Factory{
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if(modelClass.isAssignableFrom(UserViewModel::class.java))
        {
            return UserViewModel(context)as T
        }
        throw IllegalArgumentException("Unknown class")
    }

my fragment as follows

class ListFragment : Fragment() {
    private var binding:FragmentListBinding?=null
    private val sharedViewModel:UserViewModel by activityViewModels {UserViewModelFactory(requireContext())}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val fragmentBinding=FragmentListBinding.inflate(inflater,container,false);
        binding=fragmentBinding
        return fragmentBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding?.apply {
            viewModel=sharedViewModel
            lifecycleOwner=viewLifecycleOwner
            listFragment=this@ListFragment
            ToastCount()
        }
    }

    private fun ToastCount() {
        var temp=sharedViewModel.readDataFromUserTable()
        Toast.makeText(requireContext(), temp.size.toString(),Toast.LENGTH_SHORT).show()
    }
    fun addNewUser()
    {        findNavController().navigate(R.id.action_listFragment_to_addFragment)
    }
}

I can add data I see data in my database inspector but I can not read data it always return me null in my ViewModel ... I have added all necessary dependencies somebody please guild me what is it I am doing wrong? Thanks in advance

General Grievance
  • 4,555
  • 31
  • 31
  • 45
  • show your activity/fragment where you are reading data, and use ``AndroidViewModel`` rather than using ``ViewModel`` if you only wanna pass ``Application Context`` – USMAN osman Jun 24 '21 at 07:12
  • i have added my fragment in question... i am not using AndroidViewModel as i read somewhere it causes memory leaks and not recommended to use... I am able to insert data to by database but not able to read it. i dont know what is wrong i am doing! – user3459655 Jun 24 '21 at 18:10
  • 1
    whatever you put inside ``binding.apply`` remove them all.
    and your toast function remove ``var temp`` but not after equals and do this ``sharedViewModel.readDataFromUserTable().observe(viewlifecycleowner, { // do you toast here })`` and call your function(ToastCount) in ``onViewCreated()``
    – USMAN osman Jun 25 '21 at 09:12
  • I think that this [article](https://medium.com/firebase-tips-tricks/how-to-read-data-from-room-using-kotlin-flow-in-jetpack-compose-7a720dec35f50) will help. – Alex Mamo May 18 '22 at 12:25

0 Answers0