일단 여기저기 글 보면서, null-safety 지원하는 4놈으로 압축~

 

1. bloc

pub.dev/packages/bloc

 

bloc | Dart Package

A predictable state management library that helps implement the BLoC (Business Logic Component) design pattern.

pub.dev

2. provider

pub.dev/packages/provider

 

provider | Flutter Package

A wrapper around InheritedWidget to make them easier to use and more reusable.

pub.dev

 

3. riverpod

pub.dev/packages/riverpod

 

riverpod | Dart Package

A simple way to access state from anywhere in your application while robust and testable.

pub.dev

 

4. getx

pub.dev/packages/get

 

get | Flutter Package

Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX.

pub.dev

 


* 진행하는 프로젝트 특징

1. 토이프로젝트:  프로토타입(MVP), 필수 기능만 구현

2. 인원: 1명 (최대로 쥐어짜도 2명인대, 나머지 1명은 투입 여부/시기 모두 불명확)

3. 디자인: 포기 (어차피 신경써봐야 더 조잡해지는 것을 너무 잘 암)

어차피 협업해봐야 최대 2인일 것 같아서, 정형화 된 패턴이 크게 중요하지 않고

오히려 러닝커브 낮은게 더 이득이라고 판단함

provider가 쓰기도 편하고 구글에서도 좋아라해서 갈려고 하는 찰나 getx가 눈에 들어오네...

 

단순 상태관리 뿐 아니라 다른 기능도 다 맘에 듬

일단 기본적으로 context 신경쓰는 게 확연히 줄고,

언제 패키지 찾나... 없으면 언제 만드나...했던 기능들도 다수 포함되어 있음

(로케일, 테마 변경, http 유틸, validation 유틸, ...)

 

추가로 shared_preference 대신에 getx 패밀리 패키지인 get_storage도 같이 사용하면 좋을 듯

pub.dev/packages/get_storage

 

get_storage | Flutter Package

A fast, extra light and synchronous key-value storage written entirely in Dart

pub.dev

 


 

* GetX 사용할 때, 시작점으로 유용한 보일러플레이트

github.com/delay/flutter_starter

 

delay/flutter_starter

Contribute to delay/flutter_starter development by creating an account on GitHub.

github.com

 

* GetX 주요 기능

1. 상태관리

class Controller extends GetxController{
  var count = 0.obs;
  increment() => count++;
}

class Home extends StatelessWidget {

  @override
  Widget build(context) {

    // Instantiate your class using Get.put() to make it available for all "child" routes there.
    final Controller c = Get.put(Controller());

    return Scaffold(
      // Use Obx(()=> to update Text() whenever count is changed.
      appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),

      // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
      body: Center(child: ElevatedButton(
              child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
      floatingActionButton:
          FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
  }
}

class Other extends StatelessWidget {
  // You can ask Get to find a Controller that is being used by another page and redirect you to it.
  final Controller c = Get.find();

  @override
  Widget build(context){
     // Access the updated count variable
     return Scaffold(body: Center(child: Text("${c.count}")));
  }
}

2. 네비게이션

Get.to(NextScreen());
Get.toNamed('/details');
Get.back();
Get.off(NextScreen());
Get.offAll(NextScreen());

3. 유틸

3.1. snackbar & dialog

Get.snackbar('hi', 'message');
Get.defaultDialog(title: 'Alert Alert Warning Warning!');

3.2. 로케일 설정

var locale = Locale('en', 'US');
Get.updateLocale(locale);

3.3. 테마 변경

Get.changeTheme(ThemeData.light());

// 테마 & 스낵바
Get.snackbar(title, message,
	snackPosition: SnackPosition.BOTTOM,
	duration: Duration(milliseconds: milliseconds),
	backgroundColor: Get.theme.snackBarTheme.backgroundColor,
	colorText: Get.theme.snackBarTheme.actionTextColor);

3.4. http

class UserProvider extends GetConnect {
  // Get request
  Future<Response> getUser(int id) => get('http://youapi/users/$id');
  // Post request
  Future<Response> postUser(Map data) => post('http://youapi/users', body: data);
  // Post request with File
  Future<Response<CasesModel>> postCases(List<int> image) {
    final form = FormData({
      'file': MultipartFile(image, filename: 'avatar.png'),
      'otherFile': MultipartFile(image, filename: 'cover.png'),
    });
    return post('http://youapi/users/upload', form);
  }

  GetSocket userMessages() {
    return socket('https://yourapi/users/socket');
  }
}

3.5. validation

class GetUtils {
  static bool isNull(dynamic value)
  // ... 계속 ...
  static bool isBool(String value)

  static bool isVideo(String filePath)
  // ... 계속 ...
  static bool isHTML(String filePath)

  static bool isUsername(String s)
  static bool isURL(String s)
  static bool isEmail(String s)
  static bool isPhoneNumber(String s)
  static bool isDateTime(String s)
  static bool isMD5(String s)
  static bool isSHA1(String s)
  static bool isSHA256(String s)
  static bool isSSN(String s)
  static bool isBinary(String s)
  static bool isIPv4(String s)
  static bool isIPv6(String s)
  static bool isHexadecimal(String s)
  // ... 계속 ...
}

 

3.6. platform

// 웹 체크 보통 이런식인대
import 'package:flutter/foundation.dart' show kIsWeb;
if (kIsWeb) {
  // running on the web!
} else {
  // NOT running on the web! You can check for additional platforms here.
}

// 아래와 같이 제공
class GetPlatform {
  static bool get isWeb => GeneralPlatform.isWeb;
  static bool get isMacOS => GeneralPlatform.isMacOS;
  static bool get isWindows => GeneralPlatform.isWindows;
  static bool get isLinux => GeneralPlatform.isLinux;
  static bool get isAndroid => GeneralPlatform.isAndroid;
  static bool get isIOS => GeneralPlatform.isIOS;
  static bool get isFuchsia => GeneralPlatform.isFuchsia;
  static bool get isMobile => GetPlatform.isIOS || GetPlatform.isAndroid;
  static bool get isDesktop =>
      GetPlatform.isMacOS || GetPlatform.isWindows || GetPlatform.isLinux;
}

+ Recent posts