简体   繁体   中英

How to pass data down the widget tree?

I have read and understood a similar question posted here, but am having trouble applying it to my use case. I am new to Flutter and am creating an app that streams audio from a given URL using Ryan Heise's audio_service plugin. Using this plugin I instantiate an audioHandler immediately upon starting my app:

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());
}

With this audioHandler initialized, I would like to use it in child widgets. The example below demonstrates one such child widget:

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: ... 
    }
}

Note that MyApp currently just routes to EnglishHome(), but I plan on adding additional languages and instead routing MyApp to a page where a user can select their language. How can I pass audioHandler to all descendent widgets from Main()? (EnglishHome, EspHome, FrenchHome, etc?) Based upon what I have read, I will either be modifying the Key parameter of child widgets or else their BuildContext?

You can use provider package and all you need to do is use Provider.value and then use Provider.of(context) in your EnglishHome , FrenchHome etc classes.

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();
  }
}

The other answers here are also valid solutions, but what I was able to do was add an audioHandler parameter to EnglishHome:

class EnglishHome extends StatefulWidget {
  var audioHandler;

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

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

And then pass the audioHandler in when the Widget was called from my main.dart file:

@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,
        ));
  }
}

You can do this with the provider plugin.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM