在Flutter中导航时如何停止广播流?

时间:2020-03-15 14:18:01

标签: flutter dart

我正在开发当前可使用的颤动广播流应用程序。我正在使用AnimatedIcons.play_pause启动和停止广播流。目前,如果我导航到另一个页面,则该流将继续播放。当我导航到另一个页面时,我想停止流式传输(不使用暂停按钮)。原因是当您返回流媒体页面时...页面已重置为播放按钮bool isPlaying = false; 但该视频流仍在播放,因此按播放按钮将导致2个视频流播放。

这是下面的完整代码:

import 'dart:async';
import 'package:flutter_radio/flutter_radio.dart';

void main() => runApp(HarvestRadio());

class HarvestRadio extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<HarvestRadio>
    with SingleTickerProviderStateMixin {
  String url = "https://fm898.online/mystream.mp3";

  AnimationController _animationController;

  bool isPlaying = false;

  @override
  void initState() {
    super.initState();
    audioStart();
    _animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 300));
  }

  @override
  void dispose() {
    super.dispose();
    _animationController.dispose();
  }

  Future<void> audioStart() async {
    await FlutterRadio.audioStart();
    print('Audio Start OK');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Harvest Radio Online',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(
            title: const Text('Harvest Radio Online '),
            backgroundColor: Colors.blue,
            centerTitle: true,
          ),
          body: Container(
            color: Colors.blueGrey.shade900,
            child: Column(
              children: <Widget>[
                Expanded(
                  flex: 7,
                  child: Icon(
                    Icons.radio, size: 250,
                    color: Colors.lightBlue,
                  ),
                ),
                Material(
                  color: Colors.blueGrey.shade900,
                  child: Center(
                    child: Ink(
                      decoration: const ShapeDecoration(
                        color: Colors.lightBlue,
                        shape: CircleBorder(),
                      ),
                      child: IconButton(
                        color: Colors.blueGrey.shade900,
                        iconSize: 67,
                        icon: AnimatedIcon(
                          icon: AnimatedIcons.play_pause,
                          progress: _animationController,
                        ),
                        onPressed: () => _handleOnPressed(),
                      ),
                    ),
                  ),
                ),
                SizedBox(height: 50,)

              ],
            ),
          ),
        ));
  }

  void _handleOnPressed() {
    setState(() {
      FlutterRadio.play(url: url);
      isPlaying = !isPlaying;
      isPlaying
          ? _animationController.forward()
          : _animationController.reverse();
    });
  }
}

非常感谢您的帮助...谢谢!

2 个答案:

答案 0 :(得分:1)

我遇到了类似的情况,最终扩展了routeObserver来知道用户一直处于状态:

routeObserver.dart

import 'package:flutter/material.dart';

class RouteObserverUtil extends RouteObserver<PageRoute<dynamic>> {
  RouteObserverUtil({this.onChange});
  final Function onChange;
  void _sendScreenView(PageRoute<dynamic> route) {
    String screenName = route.settings.name;
    onChange(screenName);
  }

  @override
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
    super.didPush(route, previousRoute);
    if (route is PageRoute) {
      _sendScreenView(route);
    }
  }

  @override
  void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
    super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
    if (newRoute is PageRoute) {
      _sendScreenView(newRoute);
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
    super.didPop(route, previousRoute);
    if (previousRoute is PageRoute && route is PageRoute) {
      _sendScreenView(previousRoute);
    }
  }
}

这是一个用法示例:

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

import 'package:myApp/utils/routeObserver.dart';

class _RouterScreenState extends State<RouterScreen> {
  RouteObserverUtil _routeObserver;

  @override
  void initState() {
    super.initState();
    _routeObserver = RouteObserverUtil(onChange: _onChangeScreen);
  }

  void _onChangeScreen(String screen) {
    SchedulerBinding.instance.addPostFrameCallback((_) {
      print("changed to screen: " + screen);
    });
  }

  ...

}

答案 1 :(得分:0)

我找到了一个简单的解决方案,就是用MaterialApp包装我的WillPopScope……代码如下:

  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onBackPressed,
      child: MaterialApp(
          title: 'Harvest Radio Online',
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Harvest Radio Online '),
              backgroundColor: Colors.blue,
              centerTitle: true,
            ),

然后使用_onBackPressed的函数:

Future<bool>_onBackPressed(){
    FlutterRadio.stop();
    Navigator.pop(
        context, MaterialPageRoute(builder: (_) => Media()));
  }

我还必须将Navigator路由添加回上一页。

我知道这有点hack,但是可以用。谢谢大家!