【发布时间】:2021-02-19 14:53:39
【问题描述】:
我有一个具有如下文件结构的应用程序:main -> auth -> home -> secret。关键代码如下:
对于main.dart:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
StreamProvider<User>.value(value: AuthService().user),
ChangeNotifierProvider(create: (context) => SecretProvider()),
],
child: MaterialApp(
title: 'My Secrets',
home: AuthScreen(),
),
);
}
}
对于home.dart:
class HomeScreen extends StatelessWidget {
final AuthService _auth = AuthService();
@override
Widget build(BuildContext context) {
var secretProvider = Provider.of<SecretProvider>(context);
return ChangeNotifierProvider(
create: (context) => SecretProvider(),
child: Scaffold(
appBar: AppBar(
// some codes...
),
body: StreamBuilder<List<Secret>>(
stream: secretProvider.secrets,
builder: (context, snapshot) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 15.0),
child: ListView.separated(
// return 0 if snapshot.data is null
itemCount: snapshot.data?.length ?? 0,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.web),
title: Text(snapshot.data[index].title),
trailing: Icon(Icons.edit),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecretScreen(
secret: snapshot.data[index],
),
),
);
},
);
},
separatorBuilder: (context, index) {
return Divider();
},
),
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecretScreen()),
);
},
),
),
);
}
}
对于secret.dart:
class SecretScreen extends StatefulWidget {
final Secret secret;
SecretScreen({this.secret});
@override
_SecretScreenState createState() => _SecretScreenState();
}
class _SecretScreenState extends State<SecretScreen> {
// some codes...
@override
void initState() {
final secretProvider = Provider.of<SecretProvider>(context, listen: false);
// some codes...
super.initState();
}
@override
void dispose() {
// some codes...
super.dispose();
}
@override
Widget build(BuildContext context) {
final secretProvider = Provider.of<SecretProvider>(context);
return Scaffold(
// some codes...
);
}
}
这些代码工作得很好,但后来由于一些类实例生命周期问题,我决定将 ChangeNotifierProvider 从 main.dart 移动到 home.dart。新代码如下:
对于main.dart:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
StreamProvider<User>.value(value: AuthService().user),
],
child: MaterialApp(
title: 'My Secrets',
home: AuthScreen(),
),
);
}
}
对于home.dart:
class HomeScreen extends StatelessWidget {
final AuthService _auth = AuthService();
@override
Widget build(BuildContext context) {
// var secretProvider = Provider.of<SecretProvider>(context);
return ChangeNotifierProvider(
create: (context) => SecretProvider(),
child: Consumer<SecretProvider>(
builder: (context, secretProvider, child) {
return Scaffold(
appBar: AppBar(
// some codes...
),
body: StreamBuilder<List<Secret>>(
stream: secretProvider.secrets,
// stream: SecretProvider().secrets,
builder: (context, snapshot) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 15.0),
child: ListView.separated(
// return 0 if snapshot.data is null
itemCount: snapshot.data?.length ?? 0,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.web),
title: Text(snapshot.data[index].title),
trailing: Icon(Icons.edit),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecretScreen(
secret: snapshot.data[index],
),
),
);
},
);
},
separatorBuilder: (context, index) {
return Divider();
},
),
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecretScreen()),
);
},
),
);
},
),
);
}
}
基本上,我只是将ChangeNotifierProvider 移动到home.dart 并使用Consumer 传递上下文,但是这一次,每当我导航到secret 屏幕时,它都会提示我如下错误:
Could not find the correct Provider<SecretProvider> above this SecretScreen Widget
This likely happens because you used a `BuildContext` that does not include the provider
of your choice.
这个BuildContext 真的很烦我。即使我的ChangeNotifierProvider 比以前低一级,SecretScreen 小部件仍然应该知道从HomeScreen 传递的SecretProvider,因为它仍然是HomeScreen 的孩子,据我所知,上下文应包含SecretProvider。
【问题讨论】:
标签: flutter