如何在 ReorderableListView 中使用 BlocBuilder?
How to use BlocBuilder inside ReorderableListView?
当我尝试在 ReorderableListView
中使用 BlocBuilder
时,出现 Could not find the correct Provider<ThemeCubit> above this BlocBuilder<ThemeCubit, ThemeState> Widget
错误。当我在列表中拖动项目时发生错误。
示例:
List<int> _items = List<int>.generate(50, (int index) => index);
ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<ThemeCubit, ThemeState>(
builder: (___, ____) {
return Text('Item ${_items[index]}');
}
)
)
],
onReorder: (int oldIndex, int newIndex) {},
)
奇怪的是,如果我尝试使用 context.read<ThemeCubit>()
访问 bloc 数据,我不会收到错误消息。
可重现的例子 (main.dart)
当您拖动 列表中的项目时,问题重现。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SimpleCubit extends Cubit<int>
{
SimpleCubit() : super(0);
}
void main() async {
runApp(MyTrip());
}
class AppName extends StatelessWidget {
AppName({super.key});
final List<int> _items = List<int>.generate(50, (int index) => index);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider<SimpleCubit>(
create: (_) => SimpleCubit()
),
],
child: ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<SimpleCubit, int>(
builder: (_, state) {
return Text(state.toString());
}
)
)
],
onReorder: (int oldIndex, int newIndex) {},
),
),
)
);
}
}
我无法用上面提供的示例重现该问题。但我可以假设你的问题是什么。
我修改了您的 Reproducible 示例以查看您遇到的相同错误:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SimpleCubit extends Cubit<int> {
SimpleCubit() : super(0);
void onPress() {
print('press');
}
}
void main() async {
runApp(MyTrip());
}
class MyTrip extends StatelessWidget {
MyTrip({super.key});
final List<int> _items = List<int>.generate(50, (int index) => index);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider<SimpleCubit>(create: (_) => SimpleCubit()),
],
child: ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<SimpleCubit, int>(
builder: (_, state) {
return GestureDetector(
onTap: context.read<SimpleCubit>().onPress,
child: Text(state.toString()),
);
},
),
),
],
onReorder: (int oldIndex, int newIndex) {},
),
),
),
);
}
}
此错误的解释是,如果您在同一个构建方法中提供此 bloc,则无法调用 bloc 方法,因为您指的是不包含此类 bloc 的上下文:
请查看您的示例的修改版本:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SimpleCubit extends Cubit<int> {
SimpleCubit() : super(0);
void onPress() {
print('press');
}
}
void main() async {
runApp(MyTrip());
}
class MyTrip extends StatelessWidget {
const MyTrip({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider<SimpleCubit>(create: (_) => SimpleCubit()),
],
child: _MyTrip(),
),
),
);
}
}
class _MyTrip extends StatelessWidget {
_MyTrip({super.key});
final List<int> _items = List<int>.generate(50, (int index) => index);
@override
Widget build(BuildContext context) {
return ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<SimpleCubit, int>(
builder: (_, state) {
return GestureDetector(
onTap: context.read<SimpleCubit>().onPress,
child: Text(state.toString()),
);
},
),
),
],
onReorder: (int oldIndex, int newIndex) {},
);
}
}
这里我们将区块配置和使用分开。这就是它的设计用途。
只需用 BlocProvider 包装您的 MaterialApp,您的错误表明它没有找到上下文,因为您只将它提供给 ReorderableListView 小部件,因此您最好全局创建您的 bloc,以便任何具有上下文的小部件都可以调用它这样:(但它必须在您的主要 MATERIAL 应用程序中,在 MyTrip() 中)
void main() async {
runApp(MyTrip());
}
class MyTrip extends StatelessWidget {
MyTrip({super.key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider( // like this
providers: [
BlocProvider<SimpleCubit>(create: (_) => SimpleCubit()),
],
child: MaterialApp(
[...] // here it has to be your routes, theme, translation, etc...
),
);
}
当我尝试在 ReorderableListView
中使用 BlocBuilder
时,出现 Could not find the correct Provider<ThemeCubit> above this BlocBuilder<ThemeCubit, ThemeState> Widget
错误。当我在列表中拖动项目时发生错误。
示例:
List<int> _items = List<int>.generate(50, (int index) => index);
ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<ThemeCubit, ThemeState>(
builder: (___, ____) {
return Text('Item ${_items[index]}');
}
)
)
],
onReorder: (int oldIndex, int newIndex) {},
)
奇怪的是,如果我尝试使用 context.read<ThemeCubit>()
访问 bloc 数据,我不会收到错误消息。
可重现的例子 (main.dart)
当您拖动 列表中的项目时,问题重现。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SimpleCubit extends Cubit<int>
{
SimpleCubit() : super(0);
}
void main() async {
runApp(MyTrip());
}
class AppName extends StatelessWidget {
AppName({super.key});
final List<int> _items = List<int>.generate(50, (int index) => index);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider<SimpleCubit>(
create: (_) => SimpleCubit()
),
],
child: ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<SimpleCubit, int>(
builder: (_, state) {
return Text(state.toString());
}
)
)
],
onReorder: (int oldIndex, int newIndex) {},
),
),
)
);
}
}
我无法用上面提供的示例重现该问题。但我可以假设你的问题是什么。
我修改了您的 Reproducible 示例以查看您遇到的相同错误:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SimpleCubit extends Cubit<int> {
SimpleCubit() : super(0);
void onPress() {
print('press');
}
}
void main() async {
runApp(MyTrip());
}
class MyTrip extends StatelessWidget {
MyTrip({super.key});
final List<int> _items = List<int>.generate(50, (int index) => index);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider<SimpleCubit>(create: (_) => SimpleCubit()),
],
child: ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<SimpleCubit, int>(
builder: (_, state) {
return GestureDetector(
onTap: context.read<SimpleCubit>().onPress,
child: Text(state.toString()),
);
},
),
),
],
onReorder: (int oldIndex, int newIndex) {},
),
),
),
);
}
}
此错误的解释是,如果您在同一个构建方法中提供此 bloc,则无法调用 bloc 方法,因为您指的是不包含此类 bloc 的上下文:
请查看您的示例的修改版本:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SimpleCubit extends Cubit<int> {
SimpleCubit() : super(0);
void onPress() {
print('press');
}
}
void main() async {
runApp(MyTrip());
}
class MyTrip extends StatelessWidget {
const MyTrip({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider<SimpleCubit>(create: (_) => SimpleCubit()),
],
child: _MyTrip(),
),
),
);
}
}
class _MyTrip extends StatelessWidget {
_MyTrip({super.key});
final List<int> _items = List<int>.generate(50, (int index) => index);
@override
Widget build(BuildContext context) {
return ReorderableListView(
children: <Widget>[
for (int index = 0; index < _items.length; index += 1)
Container(
key: Key(index.toString()),
child: BlocBuilder<SimpleCubit, int>(
builder: (_, state) {
return GestureDetector(
onTap: context.read<SimpleCubit>().onPress,
child: Text(state.toString()),
);
},
),
),
],
onReorder: (int oldIndex, int newIndex) {},
);
}
}
这里我们将区块配置和使用分开。这就是它的设计用途。
只需用 BlocProvider 包装您的 MaterialApp,您的错误表明它没有找到上下文,因为您只将它提供给 ReorderableListView 小部件,因此您最好全局创建您的 bloc,以便任何具有上下文的小部件都可以调用它这样:(但它必须在您的主要 MATERIAL 应用程序中,在 MyTrip() 中)
void main() async {
runApp(MyTrip());
}
class MyTrip extends StatelessWidget {
MyTrip({super.key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider( // like this
providers: [
BlocProvider<SimpleCubit>(create: (_) => SimpleCubit()),
],
child: MaterialApp(
[...] // here it has to be your routes, theme, translation, etc...
),
);
}