Home > OS >  Livedata and ViewModel update infinite number of times
Livedata and ViewModel update infinite number of times

Time:10-11

when i try update model to room database. i expect it just update one time, but it update infinite number of times.

DAO

@Dao
interface UserDAO {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUserDAO(userModel : UserModel)

    @Update
    suspend fun updateUserDAO(userModel : UserModel)

    @Query("select * from user_table where _id =:id")
    fun readUserById(id : String) : LiveData<UserModel>

Repository

class UserRepository(private val userAPI: UserAPI, context : Context) {
    private val userDAO : UserDAO
    init {
        val userDatabase: UserRoomDatabase = UserRoomDatabase.getInstance(context)
        userDAO = userDatabase.getUserDao()
    }
    
     fun readUserByIdDAO(id : String): LiveData<UserModel> = userDAO.readUserById(id)
    suspend fun insertUserDAO(userModel : UserModel) = userDAO.insertUserDAO(userModel)
    suspend fun updateUserDAO(userModel : UserModel) = userDAO.updateUserDAO(userModel)
}

ViewModel

class UserViewModel(private val userRepository: UserRepository) : ViewModel() {
    val userModelResponse: MutableLiveData<Resource<UserModel>> = MutableLiveData()
    val listUserModelResponse: MutableLiveData<Resource<ArrayList<UserModel>>> = MutableLiveData()
  fun readUserByIdDAO(id : String) : LiveData<UserModel> = userRepository.readUserByIdDAO(id)

    fun insertUserDAO(userModel: UserModel) = viewModelScope.launch {
        userRepository.insertUserDAO(userModel)
    }
    fun updateUserDAO(userModel: UserModel) = viewModelScope.launch {
        userRepository.updateUserDAO(userModel)
    }
}

then i use it in MainActivity

class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: UserViewModel
    private lateinit var binding: ActivityMainBinding
    private lateinit var auth : FirebaseAuth
    private var userId = ""

    override fun onStart() {
        super.onStart()
        val navController = findNavController(R.id.fragmentHome)
        binding.bottomNavigationHome.setupWithNavController(navController)
        val userAPI = UserAPI.getInstance()
        val userRepository = UserRepository(userAPI,this)
        viewModel =
            ViewModelProvider(this, UserModelFactory(userRepository)).get(UserViewModel::class.java)
        auth = Firebase.auth
        userId = auth.currentUser!!.uid
        viewModel.readUserByIdDAO(userId).observe(this,{ userFromDAO ->
            userFromDAO.active = true
            viewModel.updateUserDAO(userFromDAO)
            Log.e(TAG,userFromDAO.toString())

        })

    }
override fun onStop() {
        super.onStop()
        Log.e(TAG,"Stop")
        viewModel.readUserByIdDAO(userId).observe(this,{ userFromDAO ->
            userFromDAO.active = false
            viewModel.updateUserDAO(userFromDAO)
            viewModel.updateUserAPI(userFromDAO)
        })
    }

what is my problem and how can i fix it?

Every day offers us many surprises; today I wish you all to have a spectacular day. I wish you all the best

CodePudding user response:

The real question is, what do you want to do? If you update the database only at onstart and onstop why do you need livedata? You said in your comment you want to check user online or offline. Why did you write it to the database? Tell us what you want to achieve and we can find another solution..

BTW, this is my answer if you want to check user is online or not:

If you want to check user online or offline why don't you just check is device online or offline? You can see how to do that here: How to check if an android device is online

The above link tells you how to make a function to check your connectivity status. If you want to do something automatically every time the network state changes, you need to run that function to check your connectivity every time while your app running. That is not effective. You can use work manager if you want to automatically detect network changes: How to trigger work manager when wifi is connected in android?

So if you know when you want to check the network status, use the first method. If you want to monitor network status and automatically do something when status changes, use the second method.

CodePudding user response:

Use an if statement so you won’t repeatedly write the same item back

if (!userFromDAO.active) {
    userFromDAO.active = true
    viewModel.updateUserDAO(userFromDAO)
}
Log.e(TAG,userFromDAO.toString()) 
  • Related