搜尋分類、套件與程式碼儲存庫

套件詳情v0.0.1

multi_app_viewer

一個工具,可同時查看和導航具有不同設定的一個應用程式

AndroidiOSWebmacOSWindowsLinux
近 30 天下載
7
喜歡數
47
Pub 分數
130

安裝套件

flutter pub add multi_app_viewer

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

多應用檢視器是一款測試工具,允許開發人員同時查看和導航單個應用的不同設定,以快速比較各種設定下的行為。它支援包括 Android、iOS、Web、macOS、Windows 和 Linux 在內的多個平台,非常適合跨平台測試。該工具透過減少每次設定變更後重構或重新啟動應用的需求,提升開發效率。它可透過 Flutter Pub 無縫整合,並專為開發與品質保證工作流程設計。

適用情境

  • 比較不同主題下的 UI/UX
  • 使用不同的環境設定測試應用程式行為
  • 驗證跨語言的本地化變更
  • 除錯平台特定的渲染問題
  • 在開發過程中進行快速配置迭代

主要特色

  • 即時應用狀態切換
  • 對多個裝置平台的支援
  • 設定差異的即時預覽
  • 透過 Flutter Pub 實現輕鬆整合
  • 內建的應用實例間導航

適合對象

  • Flutter 開發者
  • QA 測試人員
  • UI/UX 設計師
  • 跨平台應用團隊
  • 快速原型設計環境

使用建議

  • 不適用於生產建構
  • 需要手動設定設定檔
  • 多個實例可能會增加記憶體使用量
  • 僅限檢視;不適用於自動化測試
  • 最佳使用於僅限開發環境

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。

Multi App Viewer

Multi App View is a developer tool to view and navigate multiple instances of one app with different visual settings, at the same time.

Multi mode

Web demo

Scenarios:

  • easy and fast visual check of form factors and themes while developing
  • showcasing responsive/adaptive apps
  • self-service screenshots and animations creation
  • design comparison and selection

Why?

  • Lot of time and tons of boring repeating clicks spared by having multiple configurations visible
  • Cool to see and capture several synchronized screens

Features

  • show instances in row, column, stack or complex dashboard layouts
  • navigate all instances together according to the master instance
  • formatting, titles, comments, tilting
  • state broadcast
Presentation features
  • Full screen on/off
  • Hide/show the app bar
  • Preferred configuration list
  • Text only instances: you can add HTML content to highlight certain topics without the app screen
Scripting
  • Autostart and button click scripts
  • Synchronized navigation, event broadcast and configuration change
  • Auto-repeat option
Screenshot and screen-capture
  • Save screenshots of the frame (excluding the MAV appbar)
  • Record screen and convert to animated GIF
Items and configurations

Frame and item configurations

  • in code,
  • save and load config files,
  • edit interactively

Frame configuration

  • Title with HTML support
  • Background color
  • Tilt

Child configuration

  • Title and description with HTML support
  • Device frame
  • Background color
  • Tilt
  • Light or dark mode
  • Directionality (left-to-right, right-to-left)
  • Platform mechanics

Getting started

Add the package to the project

Copy the example/lib/main.dart file with a new name into your project

Replace YourApp() with your top level widget

void main() {
  runApp(const MavCounterDemo());
}

class MavCounterDemo extends StatelessWidget {
  const MavCounterDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'MAV Demo',
        debugShowCheckedModeBanner: false,
        home: MavFrameWidget(
          itemBuilder: (MavItem mavItem) {
            /* Replace MyApp() with your app widget */
            return YourApp();
          },
        ));
  }
}

Create a new run configuration targeting the new file and run or debug it. You'd see something like this, with your app on the device screens:

First impression

Apps will not run with Multi App View if they are non reentrant.

Usage

Interactive editor

Switch to edit mode on the toolbar and click on an item to configure or click on empty place to open the frame configuration dialog.

Initial view

To change the initial view, add MavFrame.loadConfiguration to the main function

  • selecting one of the predefined configurations
  • creating a configuration from code
  • or loading from file.
void main() {
  MavFrame.loadConfiguration(
    // FrameConfiguration.fromFile('C:\\Users\\kl\\Documents\\mav_config.mavc')
    FrameConfiguration.base(),
  );
  runApp(const MavCounterDemo());
}

While developing and debugging your app, during a hot reload the MAV frame should keep the interactive formatting but on restart it will use the initial view.

Configurations are not app specific, you can reuse them in different projects.

Child customization

Add mavItem parameter to your root widget

class MyApp extends StatelessWidget {
  final MavItem? mavItem;
  MyApp({super.key, this.mavItem});
}

Use mavItem and mainly mavItem.configuration fields to customize each app instance, or add to your own logic based on item index.

MaterialApp.router(
      builder: (context, rootWidget) {
        //use mavItem and mainly mavItem.configuration to customize each app instance
        return Directionality(
          textDirection: item?.configuration.textDirection ?? TextDirection.ltr,
          child: Theme(
              data: Theme.of(context).copyWith(
                  platform: mavItem?.configuration.targetPlatform),
              child: rootWidget!),
        );
      },
//...
)

Synchronized navigation
Common navigation

To navigate all instances according to the master (the first instance) add NavigationObserver


late final GoRouter _router = GoRouter(
  // MAV customization
  // add [mavTtem?.navigatorKey]
  navigatorKey: mavItem?.navigatorKey,
  // add mavItem!.navigatorObserver
  observers:
    mavItem?.navigatorObserver == null ? null : [mavItem!.navigatorObserver],
// ...
);

and an onNavigationCallback to handle and forward navigation events to the rest of the instances. The callback depends on the way of navigation in your app. For example with go_router

    MaterialApp.router(builder: (context, rootWidget) {
        item?.onNavigationCallback =
            (String routeName, int index, {Object? arguments}) {
          if (index != mavItem?.index) {
            if (arguments != null) {
              _router.goNamed(routeName,
                  queryParameters: arguments as Map<String, dynamic>);
            } else {
              _router.goNamed(routeName);
            }
          }
        };
        //...
  })

Customization inside your app

If you want to use MavItem configuration inside the app, you can obtain it via MavItemInherited.

For example, to avoid Android restorationId conflicts:

  late final MavItem? mavItem = MavItemInherited.maybeOf(context)?.item;
  
@override
String get restorationId => 'bottom_app_bar_demo${mavItem?.identifier ?? ''}';
Further synchronization

Multi App Viewer has an entry level event bus. You can push labeled values from one MAV Item, and all others may listen to those values.


  int _counter = 0;
  late final MavItem? mavItem = MavItemInherited.maybeOf(context)?.item;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
    mavItem?.publish('_counterValue', _counter);
  }

  @override
  void dispose() {
    super.dispose();
    mavItem?.dispose('_counterValue');
  }
  
  @override
  Widget build(BuildContext context) {
    mavItem?.listen('_counterValue', (value) {
      setState(() {
        _counter = value;
      });
    });

    return Scaffold(
      //...
    );
  }

If you use a state management solution, the MAV event bus might not be needed. For example, Provider counter example works out of the box when ' Providers are above MyApp instead of inside it. '

Scripts

Scripts are lists of navigation, configuration change and synchronization commands. For example:


   List script = [
    FrameConfiguration.fourPiece(),
    // navigates to details with value 33
     (-1, 'details', {'id1': '33'}),
     // navigates back to main
    (-1, '/', {'id1': '33'}),
    // send value 99 to all listeners
     ('_counterValue', 99)
  ];

   // runs the script when the toolbar menu Run scrip invoked 
   MavFrame.buttonScript = script;

   // runs the script when the app load or reloads 
   MavFrame.autoRunScript = script;
   
  // repeats the script until the stop button is pressed
   MavFrame.autoRepeat = true;

Additional information

Mentions

Although the device_preview package is not used directly, it is still an exceptional inspiration for Flutter development.

The dashboard package is used for complex layouts. That's a very promising solution.

Disclaimer

Showing the same app in multiple slots at the same time is not an end user scenario. Therefore, this is a development tool not a release feature.

Most of the Flutter apps are not reentrant (and that's OK). Running them in parallel with themself has conflicts on statics, globals, keys, local or server resources. These conflicts may result in data loss, endless loops, tricky and hard to detect bugs.

The itemBuilder and the itemInherited permits further customization and isolation of the instances.

Performance degradations are natural as more and more items are started at the same time.

Make sure that Multi App View does not impact the release quality of your app by separating/removing all related code from release builds and have separate run configurations with and without Multi App View.

Screens and platforms

Of course, all instances run on the same platform even if the device frames are different.

Big screen is good. I use the desktop target where I develop.

If you want to make a distributable with the Multi App Viewer, swap the original main.dart file with the new you've created in the Getting Started. Use it internally only, since the Multi App View is not for release versions.

This is a pure dart library, it should work on all platforms - more or less. Multi App Viewer tries to minimize the impact on the hosting app, for example no additional permission are required. That's why the file save/load is a bit simplified...
The config file save and load was not tested on Linux, MacOs and IoS. Please submit an issue if you encounter problems.

Lot of apps will not run with Multi App View if they are non reentrant. For example, in the Gallery App the Reply sample fails on a GlobalKey when running more than one instance, all others work.

Running on different platform may have different results. For example, an app running on Android may fail on restoration ids, but may run on Windows and on Web.

所屬分類

依賴

原始碼儲存庫

使用此套件的專案

暫無相關資料。