У меня есть один JSON, хранящийся в Remote Config, который содержит большую часть текста моего приложения. Если я добавлю пару "ключ-значение" к удаленному объекту и объекту JSON по умолчанию, а затем попытаюсь сослаться на это значение от клиента, клиент попытается получить доступ к значению в старом кэшированном JSON и вернет значение null, даже если значение хранится в новый JSON по умолчанию жестко запрограммирован в клиенте приложения.
Как я могу полагаться на обновленное значение по умолчанию, если обновленный удаленный JSON еще не кэширован? Другие предложения также приветствуются.
Я создал синглтон, в котором хранится текст json моего приложения по умолчанию, а также удаленный json.
В main()
я вызываю AppTextSingleton();
, а затем запускаю await AppTextSingleton.singleton.initialize();
после инициализации RemoteConfig. Я делаю все это до того, как мне позвонят runApp
.
appText
синглтона содержит все кешированные удаленные значения, а также любые значения по умолчанию, которых нет в кешированном удаленном json. Таким образом, если приложение обновляется до новой версии, которая вызывает новую пару ключ-значение из JSON, но клиент все еще работает со старой кешированной версией без пары ключ-значение, будет использоваться значение по умолчанию. .
import 'dart:convert';
import 'package:flutter/services.dart';
import '../constants.dart';
class AppTextSingleton {
Map<String, dynamic> remoteAppText =
json.decode(remoteConfig.getString("app_text"));
Map<String, dynamic> defaultAppText = {};
Map<String, dynamic> appText =
json.decode(remoteConfig.getString("app_text"));
factory AppTextSingleton() => singleton;
static final AppTextSingleton singleton = AppTextSingleton._internal();
AppTextSingleton._internal();
Future<void> initialize() async {
await setDefaultAppText();
mergeTexts();
}
Future<void> setDefaultAppText() async {
defaultAppText = await json
.decode(await rootBundle.loadString('assets/default_text.json'));
}
void mergeTexts() {
appText = mergeMap([defaultAppText, remoteAppText], acceptNull: true);
}
}
mergeMap
является модифицированной версией пакета [belatuk_merge_map 4.0.0]1. Просто скопировал один файл дротика в пакете в локальный проект и изменил функцию _copyValues, чтобы добавить только карты типа <String, dynamic>. Текущий пакет, кажется, добавляет <dynamic, dynamic>, что не соответствует потребностям RemoteConfig.
Модифицированный пакет:
dynamic _copyValues<K, V>(Map<String, dynamic> from, Map<String, dynamic> to,
bool recursive, bool acceptNull) {
for (var key in from.keys) {
if (from[key] is Map<String, dynamic> && recursive) {
if (to[key] is! Map<String, dynamic>) {
to[key] = <String, dynamic>{};
}
_copyValues(from[key] as Map<String, dynamic>,
to[key] as Map<String, dynamic>, recursive, acceptNull);
} else {
if (from[key] != null || acceptNull) {
to[key] = from[key];
}
}
}
}
Map<String, dynamic> mergeMap<K, V>(Iterable<Map<String, dynamic>> maps,
{bool recursive = true, bool acceptNull = false}) {
var result = <String, dynamic>{};
for (var map in maps) {
_copyValues(map, result, recursive, acceptNull);
}
return result;
}