Flutter Metronome App 会随着值的变化而滞后和更新

时间:2020-12-26 16:46:53

标签: flutter dart

作为 Flutter 中的第一个应用程序,我想构建一个节拍器应用程序。 UI已经搭建好了,但是我在实际的节拍器功能上还是遇到了以下问题:

  • 有时,节拍器有点滞后,刚好够用,所以您会注意到。 flutter 有没有办法让节拍器达到 100% 的精度?

  • 在演奏时不改变细分(你必须停止并启动节拍器)。如果值“tempo”和“subdivision”发生变化,它们如何自动应用于节拍器订阅?我知道 Flutter 提供了诸如 Listenable、Stream、InheritedWidget 等工具,但我还没有想出如何在现有代码中实现这些工具。

界面截图:

enter image description here

这是代码(它不完全是我写的 -> 学分):

import 'dart:io' show File;
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:quiver/async.dart';
import 'package:audioplayers/audioplayers.dart' show AudioPlayer;
import 'package:flutter/services.dart' show ByteData, rootBundle;
import 'package:path_provider/path_provider.dart' show getTemporaryDirectory;

//credits: "Andi Qu", https://stackoverflow.com/questions/51048402/flutter-audioplayers-or-metronome-lagging

ValueNotifier<int> tempo = ValueNotifier(100);
int subdivision = 1;
bool isPlaying = false;

int soundIndex = 1;
File _soundFile;

StreamSubscription<DateTime> _subscription;

Future<ByteData> _loadSound() async {
  return await rootBundle.load('assets/sounds/sound_$soundIndex.wav');
}

void _writeSound() async {
  _soundFile = File(
      '${(await getTemporaryDirectory()).path}/sounds/sound_$soundIndex.wav');
  await _soundFile.writeAsBytes((await _loadSound()).buffer.asUint8List());
  print("_writeSound executed");
}

void _playLocal() async {
  final AudioPlayer _audioPlayer = AudioPlayer();
  AudioPlayer.logEnabled = false;
  await _audioPlayer.play(_soundFile.path, isLocal: true);
}

/// The actual method that plays the metronome

void playpause() {
  print("playpause triggered");
  if (_soundFile == null) {
    print("_soundFile = null ---> Soundfile written");
    _writeSound();
  }

  if (isPlaying) {
    _subscription.cancel();
    isPlaying = false;
    print("metronome stopped");
  } else {
    _subscription = Metronome.periodic(new Duration(
            milliseconds: (60000 / (tempo.value * subdivision)).floor()))
        .listen((d) => _playLocal());
    isPlaying = true;
    print("metronome started");
  }
}

void increasetempo(int tempochange) {
  tempo.value = tempo.value + tempochange;

  if (isPlaying) {
    _subscription.cancel();
    print("_subscription canceled");
    _subscription = Metronome.periodic(new Duration(
            milliseconds: (60000 / (tempo.value * subdivision)).floor()))
        .listen((d) => _playLocal());
  }
  print("tempo changed to ${tempo.value}");
}

void decreasetempo(int tempochange) {
  tempo.value = tempo.value - tempochange;

  if (isPlaying) {
    _subscription.cancel();
    print("_subscription canceled");
    _subscription = Metronome.periodic(new Duration(
            milliseconds: (60000 / (tempo.value * subdivision)).floor()))
        .listen((d) => _playLocal());
  }
  print("tempo changed to ${tempo.value}");
}

0 个答案:

没有答案