如何将数据向下传递到小部件树?

How to pass data down the widget tree?

我已阅读并理解了一个类似的问题 ,但无法将其应用到我的用例中。我是 Flutter 的新手,正在创建一个应用程序,使用 Ryan Heise 的 audio_service 插件从给定的 URL 流式传输音频。使用这个插件,我在启动我的应用程序时立即实例化了一个 audioHandler:

late AudioHandler audioHandler;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final session = await AudioSession.instance;
  await session.configure(const AudioSessionConfiguration.music());
  audioHandler = await AudioService.init(
    builder: () => AudioPlayerHandler(),
    config: const AudioServiceConfig(
      androidNotificationChannelId: 'com.ryanheise.myapp.channel.audio',
      androidNotificationChannelName: 'Channel Name',
      androidNotificationOngoing: true,
    ),
  );
  runApp(const MyApp());
}

初始化此 audioHandler 后,我想在子窗口小部件中使用它。下面的示例演示了一个这样的子小部件:

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: "Koradi Radio",
        theme: ThemeData(
          brightness: Brightness.light,
          scaffoldBackgroundColor: Colors.white70,
        ),
        darkTheme: ThemeData(
          brightness: Brightness.dark,
        ),
        themeMode: ThemeMode.system,
        home: const EnglishHome());
  }
}

class EnglishHome extends StatefulWidget {
  const EnglishHome({Key? key}) : super(key: key);

  @override
  _EnglishHomeState createState() => _EnglishHomeState();
}


class _EnglishHomeState extends State<EnglishHome> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('English Radio'),
        backgroundColor: Colors.transparent,
      ),
      body: ... 
    }
}

请注意,MyApp 当前仅路由到 EnglishHome(),但我计划添加其他语言,而不是将 MyApp 路由到用户可以 select 他们的语言的页面。如何将 audioHandler 传递给 Main() 的所有后代小部件? (EnglishHome、EspHome、FrenchHome 等?)根据我所阅读的内容,我将修改子部件的 Key 参数或修改它们的 BuildContext?

您可以使用 provider 包,您需要做的就是使用 Provider.value,然后在您的 EnglishHomeFrenchHome 等中使用 Provider.of(context) 类.

late AudioHandler audioHandler;

Future<void> main() async {
  audioHandler = await AudioService.init(...);
  runApp(MyApp(audioHandler));
}

class MyApp extends StatelessWidget {
  final AudioHandler audioHandler;
  const MyApp(this.audioHandler, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Provider.value(
      value: audioHandler, // Providing the data above MaterialApp
      child: MaterialApp(
        home: EnglishHome(),
      ),
    );
  }
}

class EnglishHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Accessing the data. 
    final audioHandler = Provider.of<AudioHandler>(context);
    return Container();
  }
}

这里的其他答案也是有效的解决方案,但我能做的是向 EnglishHome 添加 audioHandler 参数:

class EnglishHome extends StatefulWidget {
  var audioHandler;

  EnglishHome({Key? key, this.audioHandler}) : super(key: key);

  @override
  _EnglishHomeState createState() => _EnglishHomeState();

然后在从我的 main.dart 文件调用 Widget 时传递 audioHandler:

@override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: "Radio",
        theme: ThemeData(
          brightness: Brightness.light,
          scaffoldBackgroundColor: Colors.blue[100],
        ),
        darkTheme: ThemeData(
          brightness: Brightness.dark,
        ),
        themeMode: ThemeMode.system,
        home: EnglishHome(
          audioHandler: audioHandler,
        ));
  }
}