首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用热重新启动时处理处理方法

使用热重新启动时处理处理方法
EN

Stack Overflow用户
提问于 2021-11-13 07:09:24
回答 2查看 668关注 0票数 0

是否有一种方法在使用热重新启动时正确地配置资源:

热重启加载代码更改到VM,然后重新启动颤振应用程序,失去应用程序状态。( IntelliJ和Android中的⇧⌘\,VSCode中的⇧⌘F5 )

在我的应用程序中,我有一个很大的资源(这里是一个音频播放器),它是在initState上创建的,然后在dispose中处理。

当点击按钮时,它将开始播放一首歌:

代码语言:javascript
复制
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: const MyHomePage()));
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  late AudioPlayer audioPlayer;

  @override
  void initState() {
    print("Creating audio player");
    audioPlayer = AudioPlayer();
    super.initState();
  }

  @override
  void dispose() {
    print("Disposing audio player");
    audioPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          print("Starting new song");
          final result = await audioPlayer.play(
            'https://upload.wikimedia.org/wikipedia/commons/c/c2/Toccata_and_Fugue_in_D_Minor_%28ISRC_USUAN1100350%29.mp3',
          );
          await audioPlayer.resume();
          print(result);
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

问题是当使用热重新启动时,不调用dispose方法,因此在热重新启动之前播放的歌曲不会停止,点击按钮将开始在最后一首歌曲的顶部播放另一首歌曲。

如果不调用dispose,那么在使用热重新启动时,如何正确地释放对象?

我的pubspec是默认的发布规范,添加了audioplayers依赖项:

代码语言:javascript
复制
name: flutter_application_1
description: A new Flutter project.
version: 1.0.0+1
environment:
  sdk: ">=2.16.0-10.0.dev <3.0.0"
dependencies:
  flutter:
    sdk: flutter
  audioplayers: ^0.20.1
dev_dependencies:
  flutter_test:
    sdk: flutter
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-15 10:27:45

不幸的是,没有简单的方法来解决这个问题。

热-重新启动你的应用程序基本上就像杀死它的进程和重新启动它(用更新的代码),但实际上是本地进程被杀死了。这意味着,由于热重新启动而被杀死的应用程序不能执行任何清理代码(因此不等同于热重新加载的reassemble方法)。

不幸的是,平台插件没有通知热重启(颤振引擎中有一个打开的问题,您可以将其向上更新),所以它们也不能清理热重新启动应用程序获得的资源。

一个可能的解决办法是在应用程序启动时释放所有以前获得的资源。在第一次启动时,任何东西都不会被释放,因为热重启应用程序会从上一次运行中释放资源。不幸的是,audioplayers (和其他库,如flutter_sound)没有公开任何全局的"disposeAll“API。

所以,tl;dr,最好的解决方案是@PatrickMahomes提供的,添加一个开发时按钮,在重新启动之前停止播放器(或者忽略这个问题,因为它永远不会出现在发布版本中)。但是,如果你出于某种原因真的想这么做,这里有一个

我绝对不推荐实现的丑陋和疯狂的攻击:

audioplayers中实现此功能的一种方法是将正在启动的plaing播放器的is (在启动时,而不是在应用程序被杀死时)保存到某个持久性存储中,在启动应用程序时读取它们(如上面所述),并在每个内存上调用AudioPlayer(playerId: id).release()

票数 3
EN

Stack Overflow用户

发布于 2022-01-16 14:19:17

这个问题是由热重启动引起的,不能通知插件热重启。

这个解决方案只是针对您的特定情况的一个解决方案。

一旦您初始化了播放器,我就会保存玩家ID:

代码语言:javascript
复制
Future<AudioPlayer> _initPlayer() async {
    print("Creating audio player");
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final playerId = prefs.getString('audioPlayer');
    if (playerId != null) {
      AudioPlayer(playerId: playerId).release();
    }
    final audioPlayer = AudioPlayer();
    await prefs.setString('audioPlayer', audioPlayer.playerId);
    return audioPlayer;
  }

此函数使用SharedPreferences存储playerId。每次输入播放机时,这段代码都会检查存储的ID,如果有存储的ID,则会创建一个带有该ID的AudioPlayer并释放它。然后继续创建一个新的。

因为这个函数是异步的,所以它不能在initState()中运行。

我将FloatingActionButton封装在链接到_initPlayer()函数的FutureBuilder中。

代码语言:javascript
复制
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FutureBuilder(
        future: _initPlayer(),
        builder: (BuildContext context, AsyncSnapshot<AudioPlayer> snapshot) {
          if (snapshot.hasData) {
            audioPlayer = snapshot.data!;
            return FloatingActionButton(
              onPressed: () async {
                print("Starting new song");
                await audioPlayer.play(
                  'https://upload.wikimedia.org/wikipedia/commons/c/c2/Toccata_and_Fugue_in_D_Minor_%28ISRC_USUAN1100350%29.mp3',
                );
              },
              child: const Icon(Icons.play_arrow),
            );
          }

          return FloatingActionButton(
            onPressed: () => {},
            child: const CircularProgressIndicator(),
          );
        },
      ),
    );
  }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69952232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档