问题描述
我有一个使用共享首选项实现的应用小部件。
现在我正在努力将其迁移到 Data Store。
这里的问题是如何观察/收集 appwidgetprovider(broadCastReceiver 的子类)中的 Flow 数据?
重现问题的最少代码。
class Myappwidgetprovider : appwidgetprovider() {
override fun onUpdate(
context: Context,appWidgetManager: AppWidgetManager,appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context,appWidgetManager,appWidgetId)
}
}
}
internal fun updateAppWidget(
context: Context,appWidgetId: Int
) {
RemoteViews(context.packageName,R.layout.widget_layout).also { views ->
val data = loadDataFromPreferences(context,appWidgetId)
views.setTextViewText(
R.id.textview_title,data.title
)
appWidgetManager.updateAppWidget(appWidgetId,views)
}
}
DataStoreUtil:
internal fun loadDataFromPreferences(context: Context,appWidgetId: Int): Flow<Data> {
val dataStore: DataStore<Preferences> = context.createDataStore(
name = PREFS_NAME,migrations = listof(SharedPreferencesMigration(context,PREFS_NAME))
)
val PREF_TITLE = stringPreferencesKey(PREF_PREFIX_KEY + appWidgetId + PREF_SUFFIX_TITLE)
return dataStore.data
.catch {
if (it is IOException) {
it.printstacktrace()
emit(emptyPreferences())
} else {
throw it
}
}
.map { preferences ->
// No type safety.
val title = preferences[PREF_TITLE] ?: ""
Data(title)
}
}
注意:
- Data - 自定义模型类
- loadDataFromPreferences() 使用共享首选项时返回类型为
Data
。将其更改为Flow<Data>
for DataStore 导致updateAppWidget()
行中的错误:val data = loadDataFromPreferences(context,appWidgetId)
- 因为数据类型已更改为 Flow。
解决方法
您可以使用 collect
从 Flow
获取数据
val result = loadDataFromPreferences(context,appWidgetId)
CoroutineScope(Dispatchers.Main).launch{
result.collect{ data ->
views.setTextViewText(
R.id.textview_title,data.title
}
}
,
感谢 rajan kt 的回答。
从 for train,test in kfold.split(inputs,targets):
# Define callbacks
checkpoint_path = f'/content/drive/MyDrive/Colab Notebooks/saveModel/Model 1/{fold_no}'
os.mkdir(checkpoint_path)
keras_callbacks = [
ModelCheckpoint(checkpoint_path,monitor='val_loss',save_best_only=True,mode='min')
]
x_t,x_ts = inputs[train],targets[test]
y_t,y_ts = inputs[train],targets[test]
model_history = model.fit(
train_generator,epochs=EPOCHS,verbose=1,steps_per_epoch=steps_per_epoch,validation_data=valid_generator,validation_steps=val_steps_per_epoch,callbacks=keras_callbacks).history
开始,这是解决方案的主要方面。
但是,CoroutineScope(Dispatchers.Main).launch
没有按预期工作。改用 collect()
尝试解决了问题。
在下面发布工作代码:
MyAppWidgetProvider:
first()
DataStoreUtil:
class MyAppWidgetProvider : AppWidgetProvider() {
override fun onUpdate(
context: Context,appWidgetManager: AppWidgetManager,appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
CoroutineScope(Dispatchers.Main).launch {
updateAppWidget(context,appWidgetManager,appWidgetId)
}
}
}
}
internal suspend fun updateAppWidget(
context: Context,appWidgetId: Int
) {
RemoteViews(context.packageName,R.layout.widget_layout).also { views ->
loadDataFromPreferences(context,appWidgetId)
.first {
views.setTextViewText(
R.id.textview_title,data.title
)
appWidgetManager.updateAppWidget(appWidgetId,views)
true
}
}
}