我有一个LiveData对象,该对象正在活动中的一个片段中观察。该活动通过2个广播接收器收听来自系统的广播。根据当前日期从房间中查询数据。因此,接收方会检测日期是否已更改,如果已更改,请去刷新查询。
问题是在我更改设置中的日期并返回到应用程序之后,没有触发观察者。如果我转到另一个片段并返回数据,则数据将更改,但不会更改
现在输入代码:
活动:
private lateinit var timeReceiver: MyTimeReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
timeReceiver = MyTimeReceiver()
registerReceiver(timeReceiver, filter)
registerReceiver(refreshReceiver, IntentFilter("refresh_data"))
mainFragment = MainFragment.newInstance()
}
private val refreshReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == "refresh_data") {
Timber.e("time changed, need to refresh data")
mainFragment.refreshData()
}
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(timeReceiver)
unregisterReceiver(refreshReceiver)
}
片段:
private var counter: Int = 0
private lateinit var viewModel: MainFragmentViewModel
private lateinit var date: String
companion object {
fun newInstance(): MainFragment {
return MainFragment()
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
plus_btn.setOnClickListener { addCup() }
minus_btn.setOnClickListener { decreaseCup() }
viewModel = ViewModelProviders.of(this).get(MainFragmentViewModel::class.java)
viewModel.dataList.observe(viewLifecycleOwner, Observer {
it.let { it1 ->
counter = it1.size
cup_counter.text = "$counter"
setGoalVisibility()
}
})
}
override fun onResume() {
super.onResume()
viewModel.checkCups(setDate())
}
private fun decreaseCup() {
viewModel.deleteCup(counter, date)
}
private fun addCup() {
Timber.e(date)
viewModel.insertCup(
WaterCupEntity(
System.currentTimeMillis(),
++counter,
date
)
)
}
fun refreshData() {
viewModel.checkCups(setDate())
}
private fun setDate(): String {
val dateFormat = SimpleDateFormat("dd.MM.yyyy", Locale.US)
date = dateFormat.format(Calendar.getInstance().time)
return date
}
ViewModel:
class MainFragmentViewModel(application: Application) : AndroidViewModel(application) {
private var dao: WaterCupDao
var dataList: LiveData<List<WaterCupEntity>>
private var job = Job()
private val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
private val scope = CoroutineScope(coroutineContext)
private val dateFormat: SimpleDateFormat = SimpleDateFormat("dd.MM.yyyy", Locale.US)
var date: String
init {
dao = MyCupsDb.getInstance(application, scope).getDao()
date = dateFormat.format(Calendar.getInstance().time)
Timber.e("getting all cups for date: %s", date)
dataList = dao.getAllCupsWithSameDate(date)
}
fun checkCups(date :String) {
dataList = dao.getAllCupsWithSameDate(date)
}
fun insertCup(cup: WaterCupEntity) = runBlocking {
scope.launch(Dispatchers.IO) {
dao.insert(cup)
}
}
fun deleteCup(number: Int, date: String) =
scope.launch(Dispatchers.IO) {
dao.deleteCupForDate(number, date)
}
fun deleteToday(date :String) {
scope.launch (Dispatchers.IO){
dao.deleteAllCupsForDate(date)
}
}
fun deleteAllCups() {
scope.launch (Dispatchers.IO){
dao.deleteAllCups()
}
}
}
房间db:
@Database(entities = [WaterCupEntity::class], version = 1)
abstract class MyCupsDb : RoomDatabase() {
abstract fun getDao(): WaterCupDao
companion object {
@Volatile
private var instance: MyCupsDb? = null
fun getInstance(context: Context, scope:CoroutineScope): MyCupsDb {
return instance ?: synchronized(this) {
instance ?: buildDb(context,scope).also { instance = it }
}
}
private fun buildDb(context: Context,scope:CoroutineScope): MyCupsDb {
return Room.databaseBuilder(context, MyCupsDb::class.java, "myDb")
.addCallback(WordDatabaseCallback(scope))
.build()
}
}
private class WordDatabaseCallback(
private val scope: CoroutineScope
) : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onOpen(db)
instance?.let { database ->
scope.launch(Dispatchers.IO) {
populateDatabase(database.getDao())
}
}
}
fun populateDatabase(dao: WaterCupDao) {
var word = WaterCupEntity(System.currentTimeMillis(),1,"11.01.2019")
dao.insert(word)
word = WaterCupEntity(System.currentTimeMillis(),2,"11.01.2019")
dao.insert(word)
}
}
}
MyTimeReceiver:
class MyTimeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action){
Intent.ACTION_TIMEZONE_CHANGED,
Intent.ACTION_DATE_CHANGED,
Intent.ACTION_TIME_CHANGED,
Intent.ACTION_TIME_TICK -> context.sendBroadcast(Intent("refresh_data"))
}
}
}
答案 0 :(得分:0)
因此,主要的用例是在某个事件之后触发LiveData
查询-在这种情况下是来自BroadcastReceiver
的意图-因此它被刷新了。
我想为查询添加新的参数,然后使查询工作。
我没有意识到的是,这基本上与LiveData
的设计背道而驰。 LiveData
是您订阅的数据,订阅该数据的客户端不影响它,它仅侦听其更改。
所以这里的问题是设计。
要获取新查询,您通常需要新数据(以便观察会触发)或重新订阅LiveData
-一种更困难,更复杂的方法,因为这时您需要管理订阅,因此您无需泄漏。
一旦选择了意图,我便选择通过插入来获取新数据。如果有人愿意,我可以为此发布固定代码。