[英]Flutter RepositoryProvider and Hive LateInitializationError
我有一個應用程序,我正在使用 Bloc 和 Hive。
主要.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final appDocumentDirectory =
await path_provider.getApplicationDocumentsDirectory();
Hive.init(appDocumentDirectory.path);
runApp(
const MyApp(),
);
}
在 MyApp 小部件上注冊了 MultiRepositoryProvider
return MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (context) => AccountService()),
],
child: MultiBlocProvider(
providers: [
BlocProvider<AccountBloc>(
create: (context) => AccountBloc(context.read<AccountService>()),
),
],
child: MaterialApp(
home: const AppPage(),
),
),
);
AppPage 包含 bottomNavigationBar 和一些頁面
帳號.dart
class AccountService {
late Box<Account> _accounts;
AccountService() {
init();
}
Future<void> init() async {
Hive.registerAdapter(AccountAdapter());
_accounts = await Hive.openBox<Account>('accounts');
}
在 appPage 上有 BlocBuilder
BlocBuilder<AccountBloc, AccountState>(
builder: (context, state) {
if (state.accountStatus == AccountStatus.loading) {
return const CircularProgressIndicator();
} else if (state.accountStatus == AccountStatus.error) {
Future.delayed(Duration.zero, () {
errorDialog(context, state.error);
});
}
return SingleChildScrollView(....
首次加載應用程序時,我收到LateInitializationError
,即帳戶存儲庫中的late Box <Account> _accounts
未初始化。 但是,一旦我導航到另一個頁面並返回 go, Box <Account> _accounts
初始化並顯示數據。 如何避免此錯誤並在應用程序加載時初始化 Hive 框?
你能試試這個嗎? 我認為您需要等待 Hive 初始化函數
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final appDocumentDirectory =
await path_provider.getApplicationDocumentsDirectory();
await Hive.init(appDocumentDirectory.path);
runApp(
const MyApp(),
);
}
已經有 7 個月了,但如果您仍在尋找答案,不確定它是否是最佳答案,但下面的答案應該可行。
我對您遇到的問題的理解是,出現“LateInitializationError”的原因是因為您的構造函數中的 init function 調用是異步調用的,無需等待其結果。 當您導航到另一個頁面並返回 go 時,function init 運行恰好完成。 因此,錯誤消失了。 這里的復雜性在於構造函數不能標記為異步,以便您使用該 await 關鍵字。 由於您使用的是 bloc,一種可能的解決方法是當 bloc 在 init state 中時調用 repo 的 init function。
出於演示目的,我在下面定義了 bloc 狀態和事件,您完全可以根據需要更改它們。
// bloc states
abstract class AccountState{}
class InitState extends AccountState{}
class LoadedState extends AccountState{
LoadedState(this.accounts);
final List<Account> accounts;
}
class LoadingErrorState extends AccountState{}
//bloc events
abstract class AccountEvent {}
class InitEvent extends AccountEvent {}
... // other events
在您的集團邏輯中,您可以在 InitEvent 上從您的 repo 調用 init function
class AccountBloc extends Bloc<AccountEvent, AccountState> {
AccountBloc(this.repo) : super(InitState()) {
on<InitEvent>((event, emit) async {
await repo.init();
emit(LoadedState(account: repo.getAccounts()));
});
...// define handlers for other events
}
final AccountRepository repo;
}
在您的服務 class 中,您可以從構造函數中刪除 init,例如:
class AccountService {
late Box<Account> _accounts;
AccountService();
Future<void> init() async {
Hive.registerAdapter(AccountAdapter());
_accounts = await Hive.openBox<Account>('accounts');
}
List<Account> getAccounts(){
return _accounts.values.toList();
}
}
然后在你的 bloc 構建器中,當 state 為 InitState 時,你可以將 init 事件添加到你的 bloc,如下所示:
BlocBuilder<AccountBloc, AccountState>(
builder: (context, state) {
if (state is InitState) {
context.read<AccountBloc>.add(InitEvent());
return const CircularProgressIndicator();
} else if (state is LoadingErrorState) {
Future.delayed(Duration.zero, () {
errorDialog(context, state.error);
});
}
else if (state is LoadedState){
return SingleChildScrollView(....
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.