1

I am using Room database with LiveData. In Main activity I am showing data for current day. But when new day comes and onCreate wasn't called, views shows data for previous day. How can I properly refresh my data/views in onResume?

MainActivity:

mTodayViewModel = ViewModelProviders.of(this).get(TodayDataViewModel::class.java)
    val todayDataObserver = Observer<CoffeeProductivityData> { todayData ->
        ... update views here }

    mTodayViewModel.getTodayData().observe(this, todayDataObserver)

ViewModel:

class TodayDataViewModel(application: Application) : AndroidViewModel(application) {

private val mRepository: CoffeeProductivityRepository = CoffeeProductivityRepository(application)
private val mTodayData: LiveData<CoffeeProductivityData> by lazy {
    mRepository.getTodayData()
}

fun getTodayData(): LiveData<CoffeeProductivityData> {
    return mTodayData
}}

Repository:

private var mCoffeeProductivityDao: CoffeeProductivityDao
private var mTodayData: LiveData<CoffeeProductivityData>
private var mUtilities: Utilities

init {
    val database: CoffeeProductivityDatabase = CoffeeProductivityDatabase.getDatabase(application)!!
    mCoffeeProductivityDao = database.coffeeProductivityDao()
    mUtilities = Utilities()
    mTodayData = mCoffeeProductivityDao.getTodayData(mUtilities.getTodayDate())
}

// Wrapper for getting current day data
fun getTodayData(): LiveData<CoffeeProductivityData> {
    return mTodayData
}

Query from DAO:

@Query("SELECT * from coffee_productivity WHERE date LIKE :todayDate")
fun getTodayData(todayDate: String): LiveData<CoffeeProductivityData>
OMIsie11
  • 459
  • 5
  • 19

2 Answers2

0

I think your best option is to listen to the ACTION_TIME_TICK broadcast action.

Here's an example: https://gist.github.com/sourabh86/6826730

From the documentation:

The current time has changed. Sent every minute. You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver()

if (time == midnight)
    refreshDataManually();

Check this question out, on how to refresh your LiveData manually.

dasfima
  • 4,841
  • 3
  • 21
  • 24
  • I currently try to get notified when date changes by checking current date and date in database. But I have a problem with observed data. Do You know how I can 'refresh' observed row? Because it looks like livedata is observing row for previous day – OMIsie11 Nov 18 '18 at 15:36
  • maybe you just need to re-call `mTodayViewModel.getTodayData().observe(this, todayDataObserver)`? – dasfima Nov 18 '18 at 17:46
  • I couldn't make it work properly, so I ended with restarting activity. I added answer with code. But thank You for help. – OMIsie11 Nov 18 '18 at 18:48
  • Yea, restarting the activity certainly isn't the "right" way to achieve this - but whatever works, eh? – dasfima Nov 18 '18 at 19:19
  • 1
    I am going to try to make it different way, but for now, it is sadly done this way. This app is just my learning project and that restart will be really rare, considering usage of coffee tracker app. I have used it long time and it happened one time. But I will be happy to make it proper and elegant way, and I am open for suggestions. – OMIsie11 Nov 18 '18 at 20:19
0

I couldn't make LiveData to properly reset, so I ended restarting activity. I decided to do so because it is pretty rare situation in my app use case. Broadcast receiver is registered in activity onCreate, and unregistered in onDestroy. Here is broadcast receiver that listens if date changed:

    // Broadcast receiver for detecting change of day (need to refresh MainActivity)
private val mDayChangedReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == Intent.ACTION_DATE_CHANGED) {
            isActivityRefreshNeeded = true
            Log.d("mDayChangedReceiver", "Received DAY_CHANGED broadcast")
        }
    }
}

Then I check in onResume of MainActivity if boolean isActivityRefreshNeeded is true. If it is, I reset activity:

// If User has changed settings and navigated via back button, or day changed, refresh activity
    when (isActivityRefreshNeeded) {
        true -> {
            isActivityRefreshNeeded = false
            refreshActivity()
        }
    }

It is not the best solution, but as I said, it is pretty rare situation when this refresh is needed. If someone have a better solution, I will be happy to see and implement it.

OMIsie11
  • 459
  • 5
  • 19