当我停止播放具有功能的歌曲并更改导航栏索引时,颤振音乐继续播放

Mar*_* Dz 6 dart flutter flutter-layout flutter-listview flutter-pageview

我有一个包含每个项目的音乐的列表。如果我关闭屏幕,我会更改index当前位置BottomNavigationPage并调用停止函数来停止音频,但有时这不起作用。如果歌曲正在加载过程中或用户速度非常快,歌曲将继续在不同页面上播放。

我使用https://pub.dev/packages/audioplayers插件。

这是我的缩小代码示例完整工作演示:编辑::

因此,我按照 @Ringil 的提示提供了一个完整的工作示例,其中包含我在这里面临的实际问题。这是我的代码:

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  int currentIndex =0;

  @override
  Widget build(BuildContext context) {

    // Page selector for tab list
  void _selectPage(int index) {
    print('page index: $index');
    setState(() {
      currentIndex = index;
    });
  }

  // Routes list for tab navigation Android
  final List<Widget> _pages = [
    ScreenA(),
    ScreenB(func: _selectPage),
  ];

    return Scaffold(
      appBar: AppBar(),
      body: _pages[currentIndex],
      bottomNavigationBar: SafeArea(
        child: BottomNavigationBar(
          onTap: _selectPage,
          iconSize: 22,
          currentIndex: currentIndex,
          type: BottomNavigationBarType.fixed,
          items: [
            BottomNavigationBarItem(
              backgroundColor: Theme.of(context).primaryColor,
              icon: Icon(Icons.description),
              label: 'ScreenA',
            ),
            BottomNavigationBarItem(
                backgroundColor: Theme.of(context).primaryColor,
                icon: Icon(Icons.ac_unit_outlined),
                label: 'ScreenB'),
          ],
        ),
      ),
    );
  }
}

class ScreenA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('HOME'),
    );
  }
}

class ScreenB extends StatefulWidget {
  Function func;
  ScreenB({Key key, @required this.func}) : super(key: key);
  @override
  _ScreenBState createState() => _ScreenBState();
}

class _ScreenBState extends State<ScreenB> {
  var audioPlayer = AudioPlayer(playerId: 'player');
  var audioIndex = 0;
  var audioFiles = [
    "https://docs.google.com/uc?export=open&id=1SaJWqfQuHnFtL7uqrzfYG31hzOnqDM3r",
    "https://docs.google.com/uc?export=open&id=1FZkFMjQyWguAl0RMAsYDEZ07c_Qf7gjz",
    "https://docs.google.com/uc?export=open&id=1GqrwQ3eRuiil0p-Na_R1tMAvggp9YrbH",
  ];
  var _controller = PageController();

  @override
  void initState() {
    super.initState();

// starting player
    startPlayer();

  }

  startPlayer() {
    play();
  }

// Player play class set globalindex
  Future<void> play() async {
    int result = await audioPlayer.play(audioFiles[audioIndex]);
    if (result == 1) {
      // success
    }
  }

  // Stop song instance of player
  Future<void> stop() async {
    int result = await audioPlayer.stop();
    if (result == 1) {
      // success
    }
  }

  // disposing listener if not needed or users navigates away from
  @override
  void dispose() {
    super.dispose();
    audioPlayer.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: Icon(Icons.access_alarm_sharp),
            onPressed: () async {
              await stop();
              widget.func(0);
            },
          ),
        ],
      ),
      body: PageView.custom(
          dragStartBehavior: DragStartBehavior.start,
          controller: _controller,
          physics: NeverScrollableScrollPhysics(),
          scrollDirection: Axis.horizontal,
          childrenDelegate: SliverChildBuilderDelegate((ctx, pageIndex) =>
              GestureDetector(
                  onPanUpdate: (details) async {
                    if (details.delta.dx < 0) {
                      _controller.nextPage(
                          duration: Duration(milliseconds: 200),
                          curve: Curves.easeInOut);
                      await stop();

                      setState(() {
                        audioIndex = pageIndex;
                        play();
                      });
                    }
                  },
                  child: Center(
                      child: Container(
                          width: 200,
                          height: 200,
                          color: Colors.red,
                          child: Text(audioFiles[audioIndex])))))),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

以及一个展示该问题的短视频。如果我们转到轮播屏幕,导航抛出歌曲并在加载之前关闭屏幕,它们将在我不想要的不同屏幕上播放。我也不想以某种方式“阻止”用户滑动旋转木马,直到加载歌曲为止。视频: https: //streamable.com/e/ycxwob

基本上我将代码缩减到尽可能少的程度。我采用了 Ringil 的代码,因为在他的演示中一切都工作得很好。然后我添加了越来越多的代码,直到我再次注意到错误。现在我们到了。hin 和我的示例音频文件基本上存在差异。从文件大小方面来看,我的文件并不大,但它们似乎更长,这给我们带来了我一直期待的延迟。似乎如果在关闭或更改索引之前未加载歌曲,则会发生错误。

Mal*_*ged 5

添加:“使用 WidgetsBindingObserver”

class Screen extends StatefulWidget with WidgetsBindingObserver
Run Code Online (Sandbox Code Playgroud)

您将可以访问应用程序生命周期状态:

void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.paused) {
      player.pause();
    }
  }
Run Code Online (Sandbox Code Playgroud)