Огляд FlutterFlow та автоматично створеного ним коду
Привіт, мене звати Ліза і я Flutter Developer у Customertimes. Уже понад 8 років я займаюся мобільною розробкою і стежу за розвитком технологій у цій сфері. Я перейшла з Android на Flutter розробку 3 роки тому і не шкодую про це.
Ні для кого не новина, що з кожним роком зʼявляються нові інструменти, які дозволяють оптимізувати процес розробки та роблять його якомога доступнішим для широкого кола людей. Сьогодні я хотіла б поділитися з вами досвідом використання low-code платформи для розробки мобільних застосунків — FlutterFlow.
Що таке Flutter
Спочатку трохи теорії з історією. Flutter — це набір програмного забезпечення з відкритим вихідним кодом, який створив Google для побудови мультиплатформних програм за допомогою мови програмування Dart, оптимізований для швидких програм на будь-якій платформі.
Flutter використовується для розробки міжплатформних застосунків на Android, iOS, macOS, Windows, Linux і вебзастосунків з єдиної кодової бази.
Flutter вийшов у травні 2017 року і на сьогодні, як зазначено в документації, за його допомогою було розроблено вже понад 400 000 застосунків для сотень мільйонів пристроїв.
Що таке FlutterFlow
Йдемо далі і переходимо до FlutterFlow. Це потужна low-code платформа, яку можна використовувати для розробки високоякісних мобільних і вебзастосунків на основі фреймворку Flutter. Його drag-and-drop інтерфейс дозволяє створювати юзер-інтерфейси та робочі процеси без необхідності писати код з нуля.
Крім того, він надає доступ до різноманітних готових компонентів і віджетів, які можна налаштувати відповідно до вимог конкретного застосунку.
FlutterFlow — інструмент на основі браузера, з ним можна створювати повнофункціональні масштабовані програми з інтеграцією Firebase, підтримкою API, анімацією, локалізацією, push-повідомленнями, налаштованими платежами тощо. Ви також можете додавати власні функції або віджети за допомогою Dart, щоб розширити наявний функціонал.
Однак важливо зауважити, що хоча такі low-code платформи, як FlutterFlow, є зручними для швидкої побудови прототипів і створення застосунків, вони можуть бути не найкращим вибором для складних або надто кастомізованих застосунків. У деяких випадках вам доведеться написати спеціальний код, щоб отримати бажаний функціонал.
Для кого підходить FlutterFlow
Це перш за все інструмент для нетехнічних користувачів, які завдяки йому мають змогу створити застосунки з нуля без знання мов програмування. І це досить широкий спектр застосунків — від MVP демопроєктів до повноцінних мобільних застосунків для широкої аудиторії.
Користувачі можуть створити мультиплатформний мобільний застосунок без жодного рядка коду. До того ж FlutterFlow має зручний drag-n-drop інтерфейс з можливістю переходу до дерева віджетів, і завдяки цьому застосунок не сплутати з макетом.
Саме тому розуміння фундаментальних підходів розробки для роботи з FlutterFlow було б плюсом, але на практиці це зовсім не є обов’язковим.
Ціни
FlutterFlow пропонує 4 різні плани для користувачів. Чудово, що ця платформа має серед іншого і безкоштовний план, тож можна протестувати інструмент і перевірити, чи підходить він для ваших цілей. Ви не отримаєте доступ до файлів APK, але матимете змогу запустити свій застосунок, протестувати його та переглянути код. Опція завантаження коду вимкнена для користувачів безкоштовного плану, однак ви матимете доступ до всіх файлів.
Якщо ж ви хочете працювати над проєктом разом з командою або плануєте завантажувати чи публікувати файли APK, доведеться вибрати платний тариф користування. Усі вони детально описані на сайті.
Крім того, FlutterFlow може надати експертів, які зорієнтують і можуть допомогти створити рішення з проєктуванням, прототипом, впровадженням і поданням до магазинів застосунків.
Як це працює
Перш за все, FlutterFlow пропонує вам вибрати один з уже наявних шаблонів, і ще більше спростити процес розробки. Або ж, в іншому випадку, ви можете створити застосунок самостійно та розробити свій юзер-інтерфейс з нуля.
Як приклад я використала open public API coinstats, щоб отримати та відобразити динаміку щоденних змін ціни залежно від ринкової капіталізації. Юзер-інтерфейс має ListView з елементами, який створюється динамічно на основі відповіді API. Іконки «Вгору» та «Вниз» мають відображатися залежно від того, як змінюється ціна, та з’являються на екрані з примітивною анімацією повороту.
Результат
Едітор
Ви можете написати власні функції, віджети чи дії на вкладці «Custom Code», але ви не можете змінювати код, створений автоматично UI-конструктором.
Автоматично створений код віджета Dart виглядає так:
import '/backend/api_requests/api_calls.dart'; import '/flutter_flow/flutter_flow_animations.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:provider/provider.dart'; import 'home_page_model.dart'; export 'home_page_model.dart'; class HomePageWidget extends StatefulWidget { const HomePageWidget({Key? key}) : super(key: key); @override _HomePageWidgetState createState() => _HomePageWidgetState(); } class _HomePageWidgetState extends State<HomePageWidget> with TickerProviderStateMixin { late HomePageModel _model; final scaffoldKey = GlobalKey<ScaffoldState>(); final _unfocusNode = FocusNode(); final animationsMap = { 'listViewOnPageLoadAnimation': AnimationInfo( trigger: AnimationTrigger.onPageLoad, effects: [ MoveEffect( curve: Curves.easeInOut, delay: 0.ms, duration: 800.ms, begin: Offset(0, 1000), end: Offset(0, 0), ), ], ), 'iconOnPageLoadAnimation1': AnimationInfo( trigger: AnimationTrigger.onPageLoad, effects: [ VisibilityEffect(duration: 1000.ms), RotateEffect( curve: Curves.easeInOut, delay: 1000.ms, duration: 1000.ms, begin: 0, end: 1, ), ], ), 'iconOnPageLoadAnimation2': AnimationInfo( trigger: AnimationTrigger.onPageLoad, effects: [ VisibilityEffect(duration: 1000.ms), RotateEffect( curve: Curves.easeInOut, delay: 1000.ms, duration: 1000.ms, begin: 0, end: 1, ), ], ), }; @override void initState() { super.initState(); _model = createModel(context, () => HomePageModel()); } @override void dispose() { _model.dispose(); _unfocusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, appBar: AppBar( backgroundColor: FlutterFlowTheme.of(context).primaryColor, automaticallyImplyLeading: false, title: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Markets', style: FlutterFlowTheme.of(context).title2.override( fontFamily: 'Poppins', color: Colors.white, fontSize: 22, ), ), ], ), actions: [], centerTitle: false, elevation: 2, ), body: SafeArea( child: GestureDetector( onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.max, children: [ RefreshIndicator( onRefresh: () async { setState(() => _model.pagingController?.refresh()); await _model.waitForOnePage(); }, child: PagedListView<ApiPagingParams, dynamic>( pagingController: () { if (_model.pagingController != null) { return _model.pagingController!; } _model.pagingController = PagingController( firstPageKey: ApiPagingParams( nextPageNumber: 0, numItems: 0, lastResponse: null, ), ); _model.pagingController! .addPageRequestListener((nextPageMarker) { GetMarketsInfoCall.call( start: valueOrDefault<int>( getJsonField( (nextPageMarker.lastResponse ?? ApiCallResponse({}, {}, 200)) .jsonBody, r'''$.next''', ), 1, ), ).then((listViewGetMarketsInfoResponse) { final pageItems = getJsonField( listViewGetMarketsInfoResponse.jsonBody, r'''$.coins''', ).toList() as List; final newNumItems = nextPageMarker.numItems + pageItems.length; _model.pagingController!.appendPage( pageItems, (pageItems.length > 0) ? ApiPagingParams( nextPageNumber: nextPageMarker.nextPageNumber + 1, numItems: newNumItems, lastResponse: listViewGetMarketsInfoResponse, ) : null, ); }); }); return _model.pagingController!; }(), padding: EdgeInsets.zero, shrinkWrap: true, reverse: false, scrollDirection: Axis.vertical, builderDelegate: PagedChildBuilderDelegate<dynamic>( // Customize what your widget looks like when it's loading the first page. firstPageProgressIndicatorBuilder: (_) => Center( child: SizedBox( width: 50, height: 50, child: CircularProgressIndicator( color: FlutterFlowTheme.of(context).primaryColor, ), ), ), itemBuilder: (context, _, marketsIndex) { final marketsItem = _model.pagingController!.itemList![marketsIndex]; return Padding( padding: EdgeInsetsDirectional.fromSTEB(8, 4, 8, 4), child: InkWell( onTap: () async { context.pushNamed( 'details', queryParams: { 'info': serializeParam( getJsonField( marketsItem, r'''$''', ), ParamType.JSON, ), }.withoutNulls, ); }, child: Container( width: 100, height: 100, decoration: BoxDecoration( color: FlutterFlowTheme.of(context) .secondaryBackground, ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 16, 16, 16, 16), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( getJsonField( marketsItem, r'''$.name''', ).toString(), textAlign: TextAlign.center, style: FlutterFlowTheme.of(context) .subtitle1, ), Row( mainAxisSize: MainAxisSize.max, children: [ if (getJsonField( marketsItem, r'''$.priceChange1d''', ) > 0) Icon( Icons.arrow_drop_up, color: FlutterFlowTheme.of(context) .secondaryColor, size: 56, ).animateOnPageLoad(animationsMap[ 'iconOnPageLoadAnimation1']!), if (getJsonField( marketsItem, r'''$.priceChange1d''', ) < 0) Icon( Icons.arrow_drop_down, color: Color(0xFFE0180E), size: 56, ).animateOnPageLoad(animationsMap[ 'iconOnPageLoadAnimation2']!), Text( getJsonField( marketsItem, r'''$.priceChange1d''', ).abs().toStringAsFixed(3), style: FlutterFlowTheme.of(context) .bodyText1 .override( fontFamily: 'Poppins', fontSize: 20, ), ), ], ), ], ), ), ), ), ); }, ), ), ).animateOnPageLoad( animationsMap['listViewOnPageLoadAnimation']!), ], ), ), ), ), ); } }
Скільки часу знадобиться для реалізації такого простого проєкту? Що ж, у мене це зайняло майже 20 хвилин, але на першу спробу я витратила
Досвідчений розробник без проблем реалізує такий застосунок вручну за допомогою IDE за короткий проміжок часу, але перший проєкт протягом
Чи допомогли мені знання про Flutter on Dart під час написання проєкту? Так, звісно. Чи це важливо? Ні, звісно. Усе, що вам потрібно зробити, — створити UI зі зручним інтерфейсом і написати мінімум коду для невеликих задач. Нетехнічні користувачі без проблем впораються з цим інструментом, особливо коли ми всі маємо Google і можемо знайти відповіді на все, що потрібно. Так, це займе не
Поради початківцям
- Виберіть рекомендований браузер. Як зазначено в документації, оптимальним браузером для FlutterFlow є Google Chrome. Зі свого досвіду можу доповнити: використовуючи інші браузери, ви можете зіткнутися з проблемами, повʼязаними з продуктивністю та зручністю. Мені довелося перейти на Chrome у середині проєкту. Тому краще використовувати його з самого початку.
- Не пропускайте туторіал. Він досить простий і невеликий, але в ньому зібрані всі основні функції цього інструменту. Як на мене, він трохи застарілий, але це не завадить вам знайти всі необхідні функції та ознайомитися з платформою.
- Не пропускайте Firebase setup. Під час створення проєкту вам запропонують додати до нього Firebase. Це необов’язково, але без підключення до Firebase ви матимете обмежені можливості, і вам все одно доведеться його додавати. Тому краще все налаштувати від початку. До того ж розробники Flutterflow зробили це дуже простим, що радує.
- І обов’язково зберігайте документацію під рукою, щоб мати змогу підійти до розвʼязання проблеми якнайефективнішим чином.
Висновок
Якщо ви плануєте використовувати FlutterFlow для створення застосунків, оцініть свої вимоги та визначте, чи здатна платформа задовольнити ваші потреби. Також варто враховувати такі фактори, як масштабованість, безпека та продуктивність.
Не нехтуйте силою спілкування: проконсультуйтесь з досвідченими розробниками та запийте їхню думку стосовно того, чи доцільно використовувати FlutterFlow у вашому конкретному випадку.
Хай там як, я переконана, що FlutterFlow є чудовим інструментом для реалізації власних ідей у застосунках. Ця платформа розвивається з дивовижною швидкістю, і хоча в ній трапляються помилки, розробники швидко все виправляють і додають нові функції для вдосконалення продукту.
14 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів