Преглед на файлове

移除消息冒泡,改用事件总线消息通知

gavin.chen преди 2 години
родител
ревизия
db8c77c993

+ 14 - 0
lib/controller/player_controller.dart

@@ -0,0 +1,14 @@
+import 'package:fis_common/event/event_type.dart';
+
+class PlayerStateController {
+  var trigglePlay = FEventHandler();
+
+  void play(Object sender) {
+    print("${DateTime.now()} Triggle Play");
+    trigglePlay.emit(sender, "true");
+  }
+
+  void dispose() {
+    trigglePlay.dispose();
+  }
+}

+ 17 - 1
lib/main.dart

@@ -5,6 +5,8 @@ import 'package:vid_player_demo/widgets/image_cache.dart';
 
 import 'pages/canvas_player/page.dart';
 import 'pages/image_player/page.dart';
+import 'pages/multi_canvas_player/page.dart';
+import 'pages/multi_image_player/page.dart';
 
 void main() {
   runApp(const MyApp());
@@ -25,7 +27,11 @@ class MyApp extends StatelessWidget {
         '/single_image': (BuildContext context) => const SingleImageView(),
         '/image_player': (BuildContext context) => const ImagePlayerPage(),
         '/canvas_player': (BuildContext context) => const CanvasPlayerPage(),
-        '/both_player': (BuildContext context) => const BothPlayerPage(),
+        '/both_player': (BuildContext context) => BothPlayerPage(),
+        '/multi_image_player': (BuildContext context) =>
+            const MultiImagePlayerPage(),
+        '/multi_canvas_player': (BuildContext context) =>
+            const MultiCanvasPlayerPage(),
       },
       debugShowCheckedModeBanner: false,
     );
@@ -70,6 +76,16 @@ class _MyHomePageState extends State<MyHomePage> {
             ElevatedButton(
                 onPressed: () => Navigator.pushNamed(context, '/both_player'),
                 child: const Text('Both Player')),
+            const SizedBox(height: 8),
+            ElevatedButton(
+                onPressed: () =>
+                    Navigator.pushNamed(context, '/multi_image_player'),
+                child: const Text('Multi Image Player')),
+            const SizedBox(height: 8),
+            ElevatedButton(
+                onPressed: () =>
+                    Navigator.pushNamed(context, '/multi_canvas_player'),
+                child: const Text('Multi Canvas Player')),
             const SizedBox(height: 24),
           ],
         ),

+ 0 - 5
lib/notification/player_notification.dart

@@ -1,5 +0,0 @@
-import 'package:flutter/widgets.dart';
-
-class PlayerNotification extends Notification {
-  PlayerNotification();
-}

+ 7 - 3
lib/pages/both_player/page.dart

@@ -1,11 +1,13 @@
 import 'package:flutter/material.dart';
-import 'package:vid_player_demo/notification/player_notification.dart';
+import 'package:get/get.dart';
+import 'package:vid_player_demo/controller/player_controller.dart';
 import 'package:vid_player_demo/pages/canvas_player/view.dart';
 import 'package:vid_player_demo/pages/image_player/view.dart';
 
 class BothPlayerPage extends StatelessWidget {
-  const BothPlayerPage({Key? key}) : super(key: key);
+  BothPlayerPage({Key? key}) : super(key: key);
   final vidURL = "http://cdn-bj.fis.plus/093BE20682B14BFB95D811F221A2B2FD.vid";
+  final _playerStateController = Get.put(PlayerStateController());
   @override
   Widget build(BuildContext context) {
     return Scaffold(
@@ -14,9 +16,11 @@ class BothPlayerPage extends StatelessWidget {
         ),
         body: Column(
           children: [
+            const SizedBox(height: 24),
             ElevatedButton(
-                onPressed: () => {PlayerNotification().dispatch(context)},
+                onPressed: () => {_playerStateController.play(context)},
                 child: const Text("Play Together")),
+            const SizedBox(height: 24),
             Row(
               children: <Widget>[
                 Expanded(

+ 41 - 22
lib/pages/canvas_player/view.dart

@@ -2,14 +2,21 @@ import 'package:fis_measure/index.dart';
 import 'package:fis_measure/interfaces/process/player/play_controller.dart';
 import 'package:fis_vid/data_host/data_host.dart';
 import 'package:flutter/material.dart';
-import 'package:vid_player_demo/notification/player_notification.dart';
+import 'package:get/get.dart';
+import 'package:vid_player_demo/controller/player_controller.dart';
 import 'package:vid_player_demo/widgets/image_cache.dart';
 
 import 'widgets/canvas_player.dart';
 
 class CanvasPlayerView extends StatefulWidget {
-  const CanvasPlayerView(this.vidURL, {Key? key}) : super(key: key);
+  const CanvasPlayerView(
+    this.vidURL, {
+    Key? key,
+    this.viewSize = const Size(600, 500),
+  }) : super(key: key);
   final String vidURL;
+  final Size viewSize;
+
   @override
   _CanvasPlayerViewState createState() => _CanvasPlayerViewState();
 }
@@ -20,6 +27,10 @@ class _CanvasPlayerViewState extends State<CanvasPlayerView> {
   VidDataHost? _vidDataHost;
   VidDataHost get dataHost => _vidDataHost!;
   bool _ifInit = false;
+
+  /// 外部播放状态控制器
+  PlayerStateController? _playerStateController;
+  PlayerStateController get playerStateController => _playerStateController!;
   void loadVidDataHost(String url) {
     print("${DateTime.now()} Load vid data host");
     _vidDataHost = VidDataHost(url);
@@ -51,46 +62,53 @@ class _CanvasPlayerViewState extends State<CanvasPlayerView> {
     playerController.pause();
   }
 
+  void onClickPlay(Object sender, dynamic e) {
+    print("${DateTime.now()} receive Play $e");
+    clickPlay();
+  }
+
   @override
   void initState() {
     super.initState();
     loadVidDataHost(widget.vidURL);
+    _playerStateController = Get.find<PlayerStateController>();
+    playerStateController.trigglePlay.addListener(onClickPlay);
   }
 
   @override
   Widget build(BuildContext context) {
-    return NotificationListener<PlayerNotification>(
-        onNotification: ((notification) {
-          clickPlay();
-          return false;
-        }),
-        child: Center(
-          child: Column(
+    return Center(
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+        children: [
+          SizedBox(
+            width: widget.viewSize.width,
+            height: widget.viewSize.height,
+            child: RepaintBoundary(
+              child: VidCanvasPlayer(
+                _playerController as VidPlayerController,
+              ),
+            ),
+          ),
+          const Text('基于 Canvas 的播放器'),
+          Row(
             mainAxisAlignment: MainAxisAlignment.spaceEvenly,
             children: [
-              const ShowImageCache(),
               ElevatedButton(
                   onPressed: () {
                     clickPlay();
                   },
-                  child: const Text('Play')),
+                  child: const Text('Play')),
               ElevatedButton(
                   onPressed: () {
                     clickPause();
                   },
-                  child: const Text('Pause')),
-              SizedBox(
-                width: 600,
-                height: 600,
-                child: RepaintBoundary(
-                  child: VidCanvasPlayer(
-                    _playerController as VidPlayerController,
-                  ),
-                ),
-              ),
+                  child: const Text('⏸ Pause')),
             ],
           ),
-        ));
+        ],
+      ),
+    );
   }
 
   @override
@@ -98,6 +116,7 @@ class _CanvasPlayerViewState extends State<CanvasPlayerView> {
     print("CanvasPlayerView dispose");
     playerController.dispose();
     dataHost.release();
+    playerStateController.trigglePlay.removeListener(onClickPlay);
     super.dispose();
   }
 }

+ 1 - 1
lib/pages/canvas_player/widgets/canvas_player.dart

@@ -123,7 +123,7 @@ class _VidCanvasPlayerState extends State<VidCanvasPlayer> {
     return Stack(
       children: [
         Text(
-            "当前帧:${widget.controller.currentFrameIndex} \n估算平均帧率:$curFPS fps \n应用刷新率:$getScreenFPS fps"),
+            "当前帧:${widget.controller.currentFrameIndex} \n估算平均帧率:$curFPS fps \n"),
         Container(
           alignment: Alignment.center,
           child: child,

+ 36 - 14
lib/pages/image_player/view.dart

@@ -2,13 +2,20 @@ import 'package:fis_measure/index.dart';
 import 'package:fis_measure/interfaces/process/player/play_controller.dart';
 import 'package:fis_vid/data_host/data_host.dart';
 import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:vid_player_demo/controller/player_controller.dart';
 import 'package:vid_player_demo/widgets/image_cache.dart';
 
 import 'widgets/image_player.dart';
 
 class ImagePlayerView extends StatefulWidget {
-  const ImagePlayerView(this.vidURL, {Key? key}) : super(key: key);
+  const ImagePlayerView(
+    this.vidURL, {
+    Key? key,
+    this.viewSize = const Size(600, 500),
+  }) : super(key: key);
   final String vidURL;
+  final Size viewSize;
 
   @override
   _ImagePlayerViewState createState() => _ImagePlayerViewState();
@@ -21,6 +28,9 @@ class _ImagePlayerViewState extends State<ImagePlayerView> {
   VidDataHost get dataHost => _vidDataHost!;
   bool _ifInit = false;
 
+  /// 外部播放状态控制器
+  PlayerStateController? _playerStateController;
+  PlayerStateController get playerStateController => _playerStateController!;
   void loadVidDataHost(String url) {
     print("${DateTime.now()} Load vid data host");
     _vidDataHost = VidDataHost(url);
@@ -52,10 +62,17 @@ class _ImagePlayerViewState extends State<ImagePlayerView> {
     playerController.pause();
   }
 
+  void onClickPlay(Object sender, dynamic e) {
+    print("${DateTime.now()} receive Play $e");
+    clickPlay();
+  }
+
   @override
   void initState() {
     super.initState();
     loadVidDataHost(widget.vidURL);
+    _playerStateController = Get.find<PlayerStateController>();
+    playerStateController.trigglePlay.addListener(onClickPlay);
   }
 
   @override
@@ -64,26 +81,31 @@ class _ImagePlayerViewState extends State<ImagePlayerView> {
       child: Column(
         mainAxisAlignment: MainAxisAlignment.spaceEvenly,
         children: [
-          const ShowImageCache(),
-          ElevatedButton(
-              onPressed: () {
-                clickPlay();
-              },
-              child: const Text('Play')),
-          ElevatedButton(
-              onPressed: () {
-                clickPause();
-              },
-              child: const Text('Pause')),
           SizedBox(
-            width: 600,
-            height: 600,
+            width: widget.viewSize.width,
+            height: widget.viewSize.height,
             child: RepaintBoundary(
               child: VidImagePlayer(
                 _playerController as VidPlayerController,
               ),
             ),
           ),
+          const Text('基于 Image 的播放器'),
+          Row(
+            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+            children: [
+              ElevatedButton(
+                  onPressed: () {
+                    clickPlay();
+                  },
+                  child: const Text('▶ Play')),
+              ElevatedButton(
+                  onPressed: () {
+                    clickPause();
+                  },
+                  child: const Text('⏸ Pause')),
+            ],
+          ),
         ],
       ),
     );

+ 68 - 0
lib/pages/multi_canvas_player/page.dart

@@ -0,0 +1,68 @@
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:vid_player_demo/controller/player_controller.dart';
+import 'package:vid_player_demo/pages/canvas_player/view.dart';
+import 'package:vid_player_demo/pages/image_player/view.dart';
+
+class MultiCanvasPlayerPage extends StatefulWidget {
+  const MultiCanvasPlayerPage({Key? key}) : super(key: key);
+  @override
+  _MultiCanvasPlayerPageState createState() => _MultiCanvasPlayerPageState();
+}
+
+class _MultiCanvasPlayerPageState extends State<MultiCanvasPlayerPage> {
+  final vidURLs = [
+    "http://cdn-bj.fis.plus/093BE20682B14BFB95D811F221A2B2FD.vid",
+    "http://cdn-bj.fis.plus/f2d1607f66cc42d0b4a6f4e55afbaeca.vid",
+    "http://cdn-bj.fis.plus/1fb270dbb35e448a8792eb46df882264.vid",
+    "http://cdn-bj.fis.plus/95867692c39b4293bc0928192d1b53cb.vid",
+    "http://cdn-bj.fis.plus/582ba3077ea64ace882a7e11577a842b.vid",
+    "http://cdn-bj.fis.plus/ae37b3910cea406484f76da7b002708e.vid",
+    "http://cdn-bj.fis.plus/1d21144f3e524477bb8471d8d66da603.vid",
+    "http://cdn-bj.fis.plus/1fb270dbb35e448a8792eb46df882264.vid",
+    "http://cdn-bj.fis.plus/95867692c39b4293bc0928192d1b53cb.vid",
+  ];
+
+  final _playerStateController = Get.put(PlayerStateController());
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        appBar: AppBar(
+          title: const Text("多个播放器同时播放"),
+        ),
+        body: Column(
+          children: [
+            const SizedBox(height: 24),
+            ElevatedButton(
+                onPressed: () => {_playerStateController.play(context)},
+                child: const Text("Play Together")),
+            const SizedBox(height: 24),
+            SizedBox(height: 800, child: buildPlayersGrid(vidURLs)),
+          ],
+        ));
+  }
+
+  Widget buildPlayersGrid(List<String> urls) {
+    return GridView.count(
+      crossAxisCount: 3,
+      childAspectRatio: 1,
+      shrinkWrap: true,
+      children: urls
+          .map((url) => CanvasPlayerView(url, viewSize: const Size(300, 300)))
+          .toList(),
+    );
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    Get.delete<PlayerStateController>();
+    _playerStateController.dispose();
+  }
+}

+ 67 - 0
lib/pages/multi_image_player/page.dart

@@ -0,0 +1,67 @@
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:vid_player_demo/controller/player_controller.dart';
+import 'package:vid_player_demo/pages/image_player/view.dart';
+
+class MultiImagePlayerPage extends StatefulWidget {
+  const MultiImagePlayerPage({Key? key}) : super(key: key);
+  @override
+  _MultiImagePlayerPageState createState() => _MultiImagePlayerPageState();
+}
+
+class _MultiImagePlayerPageState extends State<MultiImagePlayerPage> {
+  final vidURLs = [
+    "http://cdn-bj.fis.plus/093BE20682B14BFB95D811F221A2B2FD.vid",
+    "http://cdn-bj.fis.plus/f2d1607f66cc42d0b4a6f4e55afbaeca.vid",
+    "http://cdn-bj.fis.plus/1fb270dbb35e448a8792eb46df882264.vid",
+    "http://cdn-bj.fis.plus/95867692c39b4293bc0928192d1b53cb.vid",
+    "http://cdn-bj.fis.plus/582ba3077ea64ace882a7e11577a842b.vid",
+    "http://cdn-bj.fis.plus/ae37b3910cea406484f76da7b002708e.vid",
+    "http://cdn-bj.fis.plus/1d21144f3e524477bb8471d8d66da603.vid",
+    "http://cdn-bj.fis.plus/1fb270dbb35e448a8792eb46df882264.vid",
+    "http://cdn-bj.fis.plus/95867692c39b4293bc0928192d1b53cb.vid",
+  ];
+
+  final _playerStateController = Get.put(PlayerStateController());
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        appBar: AppBar(
+          title: const Text("多个播放器同时播放"),
+        ),
+        body: Column(
+          children: [
+            const SizedBox(height: 24),
+            ElevatedButton(
+                onPressed: () => {_playerStateController.play(context)},
+                child: const Text("Play Together")),
+            const SizedBox(height: 24),
+            SizedBox(height: 800, child: buildPlayersGrid(vidURLs)),
+          ],
+        ));
+  }
+
+  Widget buildPlayersGrid(List<String> urls) {
+    return GridView.count(
+      crossAxisCount: 3,
+      childAspectRatio: 1,
+      shrinkWrap: true,
+      children: urls
+          .map((url) => ImagePlayerView(url, viewSize: const Size(300, 300)))
+          .toList(),
+    );
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    Get.delete<PlayerStateController>();
+    _playerStateController.dispose();
+  }
+}