패키지, 저장소 및 앱 카테고리 검색

패키지 상세v4.1.0

one_context

OneContext는 BuildContext 없이 다이얼로그, 오버레이, 네비게이션, 테마* 및 MediaQuery*를 처리하는 간단한 방법을 제공합니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
1.2천
좋아요
209
Pub 점수
140

패키지 설치

flutter pub add one_context

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

OneContext는 BuildContext 없이 대화 상자, 오버레이, 네비게이션 및 테마 및 미디어 쿼리 데이터에 액세스하는 것을 간소화하는 Flutter/Dart 패키지입니다. 전체 위젯 트리에서 앱 상태와 UI 상호작용을 관리하기 위한 전역 메서드를 제공하여 어디서든 알림을 표시하거나 탐색하거나 컨텍스트에 따라 값에 접근하는 것이 쉬워집니다. 복잡한 Flutter 애플리케이션에서 부가 코드를 줄이고 코드 유지보수성을 높이는 데 이상적입니다.

사용 사례

  • BuildContext 없이 대화 상자 표시
  • 앱 내 전역 탐색
  • 테마 및 미디어 쿼리 데이터를 전역적으로 액세스하기
  • 오버레이 및 팝업 관리
  • UI 요소의 상태 관리를 단순화하기
  • 유틸리티 함수에서 BuildContext에 대한 의존도 줄이기

주요 기능

  • BuildContext 필요 없음
  • 전역 대화 상자 및 오버레이 관리
  • 어디서든 쉽게 탐색하기
  • Theme 및 MediaQuery에 전역적으로 액세스
  • 최소한의 보일러플레이트 코드
  • 크로스 플랫폼 지원

적합한 대상

  • 대규모 플러터 앱
  • 간편한 컨텍스트 처리를 원하는 개발자
  • 자주 대화상자와 오버레이가 있는 앱
  • 일관된 UI 동작을 원하는 팀
  • BuildContext 종속성을 줄이려는 프로젝트
  • 전역 접근이 필요한 유틸리티 함수

고려 사항

  • 표준 위젯 라이프사이클을 건너뛸 수 있음
  • 간단한 경우에서의 과도한 사용 가능성
  • 신중한 상태 관리가 필요합니다
  • 깊이 중첩된 컨텍스트 기반 로직에 적합하지 않음
  • 제한된 디버깅 시각화
  • 명확한 아키텍처 경계와 함께 사용하는 것이 가장 좋습니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Fork   Star   Watches

Pub Version PRs Welcome

logo

One Context to rule them all

OneContext provides a simple way to deal with Dialogs, Overlays, Navigations, Theme* and MediaQuery* with no need of BuildContext.

If you are Flutter developer, you don’t have to learn something new. This package use the same identificators and names from framework. It’s not a specialized* implementation, so you have the power to create and do not get blocked because of that.

If you are Flutter package developer, OneContext can be very useful too! You can create a custom dialogs package with no need BuildContext, and release a version, that do not depends of the context, to the comunity.

one_context_demo

BuildContext always is needed (in some cases we need to choose carefully the specific one to make things work as expected), but, to global things, like dialogs, it can be reached by OneContext package. 🎯

🎮 Let's start

⚠ Important: Configure MaterialApp. e.g.

/// important: Use [OneContext().builder] in `MaterialApp` builder, in order to show dialogs and overlays.
/// important: Use [OneContext().key] in `MaterialApp` navigatorKey, in order to navigate.
return MaterialApp(
    builder: OneContext().builder,
    navigatorKey: OneContext().key,
    ...
);
There are 2 ways to get OneContext singleton instance, OneContext() or OnceContext.intance. e.g.
    OneContext().pushNamed('/detail_page');
    OneContext.instance.pushNamed('/detail_page');
There are controllers to use navigation, overlays and dialogs. e.g.
    OneContext().navigator.pushNamed(...);
    OneContext().dialog.showDialog(...);
    OneContext().overlay.addOverlay(...);
Or, you can use the shortcuts ;)
    OneContext().pushNamed(...);
    OneContext().showDialog(...);
    OneContext().addOverlay(...);
    
    // and can access info from:
    // OneContext().mediaQuery ...
    // OneContext().textTheme ...
    // OneContext().theme ...
OneContext is:
  • Fast (O(1))
  • Easy to learn/use
  • It use same native function names from Flutter, to keep it simple and intuitive ;)

💬 How to show Dialogs with no need of the BuildContext?

// example snackBar
OneContext().showSnackBar(
    builder: (_) => SnackBar(content: Text('My awesome snackBar!'))
);
// example dialog
OneContext().showDialog(
    // barrierDismissible: false,
    builder: (_) => AlertDialog( 
        title: new Text("The Title"),
        content: new Text("The Body"),
    )
);
// example bottomSheet
OneContext().showBottomSheet(
    builder: (context) => Container(
    alignment: Alignment.topCenter,
    height: 200,
    child: IconButton(
        icon: Icon(Icons.arrow_drop_down),
        iconSize: 50,
        color: Colors.white,
        onPressed: () => Navigator.of(context).pop('sucess')), // or OneContext().popDialog('sucess');
    ),
);
// example modalBottomSheet
OneContext().showModalBottomSheet<String>(
    builder: (context) => Container(
        child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
            ListTile(
                leading: Icon(Icons.music_note),
                title: Text('Music'),
                onTap: () => OneContext().popDialog('Music'); //Navigator.of(context).pop('Music')),
            ListTile(
                leading: Icon(Icons.videocam),
                title: Text('Video'),
                onTap: () => Navigator.of(context).pop('Video'),
            ),
            SizedBox(height: 45)
            ],
        ),
    )
);

⛵ How to navigate? (All methods from Navigator Class are available)

// go to second page using named route
OneContext().pushNamed('/second');
// go to second page using MaterialPageRoute
OneContext().push(MaterialPageRoute(builder: (_) => SecondPage()));
// go back from second page
OneContext().pop();
// Pop dialogs
OneContext().popDialog();
// Retrieve data from route when it's pops
String result = await OneContext().push<String>(MaterialPageRoute(builder: (_) => SecondPage()));
print(result);

🍰 How to show Overlays?

// show the default progress indicator
OneContext().showProgressIndicator();
// hide the default progress indicator
OneContext().hideProgressIndicator();
// show the default progress indicator with some colors
OneContext().showProgressIndicator(
    backgroundColor: Colors.blue.withOpacity(.3),
    circularProgressIndicatorColor: Colors.white
);

// Later
OneContext().hideProgressIndicator();
// Show a custom progress indicator
OneContext().showProgressIndicator(
    builder: (_) => MyAwesomeProgressIndicator();
);

// Later
OneContext().hideProgressIndicator();
// Show a custom widget in overlay stack

String myCustomAndAwesomeOverlayId = UniqueKey().toString();

OneContext().addOverlay(
    overlayId: myCustomAndAwesomeOverlayId,
    builder: (_) => MyCustomAndAwesomeOverlay()
);

// Later
OneContext().removeOverlay(myCustomAndAwesomeOverlayId);

🎨 Changing Dark and Light theme mode

Breaking change: OneHotReload becomes OneNotification
⚠ Please check consideration on Theme and MediaQuery topic
OneNotification<OneThemeChangerEvent>(
  stopBubbling: true, // avoid bubbling to ancestors
  builder: (_, __) {
    return MaterialApp(
      builder: OneContext().builder,
      themeMode: OneThemeController.initThemeMode(ThemeMode.light),
      theme: OneThemeController.initThemeData(ThemeData(brightness: Brightness.light)),
      darkTheme: OneThemeController.initDarkThemeData(ThemeData(brightness: Brightness.dark)),
      ...
    );
);

// Later...
OneContext().oneTheme.toggleMode();

// Or change only the dark theme
OneContext().oneTheme.changeDarkThemeData(
  ThemeData(
    primarySwatch: Colors.amber,
    brightness: Brightness.dark
 )
);

🚧 Reload, Restart and Reboot the app (Need bubbling events or data?)

First define the data type in type generics, after that, you can rebuild multiple ancestors widgets that listen the same data type. This is used for the package in this example, to change ThemeMode and Locale and even Restart the app entirely.
OneNotification<List<Locale>>(
      onVisited: (context, localeList) {
        print('widget visited!');
      },
      stopBubbling: true, // avoid the data bubbling to ancestors widgets
      initialData: _localeEnglish, // [data] is null during boot of the application, but you can set initialData
      rebuildOnNull: true, // Allow other entities reload this widget without messing up currenty data (Data is cached on first event)
      builder: (context, localeList) {
        return MaterialApp(
          supportedLocales: localeList,
        );
      },
    );
Need to dispatch more specialized data/event?

// My Specialized Event
class MySpecializedEvent {
  final String text;
  MySpecializedEvent(this.text);
}

// Widget
OneNotification<MySpecializedEvent>(
  builder: (context, event) {
    return Text(event.text);
  },
)

// Later, in children, call `OneNotifier.notify` to get ancestors notified
OneNotifier.notify(
  context,
  NotificationPayload(
    data: MySpecializedEvent('Nice!');
  )
);
Reload and Restart the app
// Place that widget on most top
OneNotification(
  builder: (_, __) => child
);

// Later... in children

// Dont lose state
OneNotification.softReloadRoot(context);

// Lose state
OneNotification.hardReloadRoot(context);
Reboot and load different apps
// Set the main() function
void main() => OnePlatform.app = () => MyApp();

// Later... Call reboot without recreating root app
OnePlatform.reboot();

// Later... Call reboot recreating the entire application
OnePlatform.reboot(
  builder: () => MyApp()
);

// You even can load an entire different app
OnePlatform.reboot(
  builder: () => MyApp2()
);

⚙ Theme and MediaQuery

print('Platform: ' + OneContext().theme.platform); // TargetPlatform.iOS
print('Orientation: ' + OneContext().mediaQuery.orientation); // Orientation.portrait

[IMPORTANT] If you need get widget rebuild on theme data changes using OneContext().oneTheme.toggleMode();, please consider to use the traditional way Theme.of(context) when getting theme data inside widget.

@override
  Widget build(BuildContext context) {

    return Container(
      color: Theme.of(context).primaryColor, // Theme.of(context)
      height: 100,
      width: 100,
    );
  }

Or you can call Theme.of(context); in the begining of build method instead;

e.g.

@override
  Widget build(BuildContext context) {
    
    // Get changes by you currently context, and ensure the rebuild on theme data changes on
    // OneContext().oneTheme.toggleMode(), OneContext().oneTheme.changeDarkThemeData() or OneContext().oneTheme.changeThemeData() events.
    Theme.of(context);

    return Container(
      color: OneContext().theme.primaryColor, // OneContext().theme
      height: 100,
      width: 100,
    );
  }

In initState or inside class constructor (now it's possible)
@override
  void initState() {
    super.initState();

    OneContext().showDialog(
        builder: (_) => AlertDialog(
          title: new Text("On Page Load"),
          content: new Text("Hello World!"),
        ),
      );

🚦 Warnings

* OneContext().theme and OneContext().mediaQuery are global instances of the root of the widget tree. Use it with care! It can reproduce unexpected behavior if you don't understand it.

* OneContext().context is like a root context, so, it should not be used directly, as it can reproduce unexpected behaviors, unless you have a understanding how it works. It shouldn't work well with InheritedWidget for example.

* This package only uses specialized implementation in Overlays, to make things easy and ensure a quick start.

👨‍💻👨‍💻 Contributing

Contributions of any kind are welcome! I'll be glad to analyse and accept them! 👾
Sponsor

Buy Me A Coffee

카테고리

의존성

의존성 목록 2 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.