SlideShare a Scribd company logo
1 of 38
Download to read offline
Supercharge Flutter
Declarative UI with code
generation
Emanuele Papa
droidcon London 2021
Working at Zest One in Chiasso, Switzerland
Who I am?
Emanuele Papa, Android Developer
Find me at www.emanuelepapa.dev
Declarative UI
Imperative UI -> Declarative UI
Jetpack Compose and SwiftUI
Unfortunately, not perfect yet
No more XML or UIKit
Padding in Flutter
Padding(
padding: EdgeInsets.all(16.0),
child: Text("Hello droidcon!")
);
What we want
- Make the code easy to write
- Avoid errors caused by distraction
- Minimize code duplication
- Make the IDE our best friend
- Improve our productivity
Looking for improvements
Someone else experienced the same struggle
Some libraries are available on GitHub
It's an improvement, but you still need to add the
Padding value manually
The missing thing
PaddingTop(16.0, child: Text("Hello droidcon!"));
Design System Padding
No need to add the Padding value manually,
it's specified in the class name
MediumTopPadding(child: Text("Hello droidcon!"));
How to create these
widgets?
Paddinger
How to use Paddinger?
dependencies:
paddinger_annotations: [latestVersionHere]
dev_dependencies:
paddinger: [latestVersionHere]
Add these dependencies to your pubspec.yaml
How to use Paddinger?
Create a paddings.dart file which contains your
PADDING_ definitions
@paddinger
const double PADDING_MEDIUM = 16.0;
@paddinger
const double PADDING_LARGE = 24.0;
How to use Paddinger?
Add material or cupertino import
Add part directive
// ignore: unused_import
import 'package:flutter/material.dart';
part 'paddings.g.dart';
Start the code generation
Now run
flutter pub run build_runner build --delete-conflicting-
outputs
What's the result?
MediumAllPadding
MediumLeftPadding
MediumTopPadding
MediumRightPadding
MediumBottomPadding
MediumHorizontalPadding
MediumVerticalPadding
MediumLeftTopPadding
MediumLeftBottomPadding
MediumRightTopPadding
MediumRightBottomPadding
paddings.g.dart
LargeAllPadding
LargeLeftPadding
LargeTopPadding
LargeRightPadding
LargeBottomPadding
LargeHorizontalPadding
LargeVerticalPadding
LargeLeftTopPadding
LargeLeftBottomPadding
LargeRightTopPadding
LargeRightBottomPadding
What's the result?
class MediumAllPadding extends Padding {
const MediumAllPadding({Key? key, required Widget child})
: super(
key: key,
padding: const EdgeInsets.all(PADDING_MEDIUM),
child: child);
}
Do not add it to your version control system
How to use them
Just import paddings.dart in your widgets,
it also contains all the generated classes created in
paddings.g.dart
Let's deep dive inside
paddinger source code!
Paddinger source code
Monorepo with 2 projects:
- paddinger
- paddinger_annotations
Paddinger source code
///Annotation used by paddinger to identify PADDING_ constants
class Paddinger {
const Paddinger();
}
///Helper object for [Paddinger] annotation
const paddinger = Paddinger();
paddinger.dart
Paddinger source code
dependencies:
analyzer: ^1.5.0
build: ^2.0.0
source_gen: ^1.0.0
recase: ^4.0.0
paddinger_annotations: ^0.1.1
#local development
#paddinger_annotations:
# path: ../paddinger_annotations/
dev_dependencies:
test: 1.16.8
pubspec.yaml
Paddinger source code
builders:
paddinger_generator:
import: "package:paddinger/paddinger.dart"
builder_factories: ["paddingerGenerator"]
build_extensions: {".dart": [".paddinger.g.part"]}
build.yaml
Paddinger source code
///Paddinger generator used with [Builder]
Builder paddingerGenerator(BuilderOptions options) =>
SharedPartBuilder([PaddingerGenerator()],
'paddinger_generator');


paddinger.dart
Paddinger source code
class PaddingerGenerator extends GeneratorForAnnotation<Paddinger> {
@override
FutureOr<String> generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
final constantName = element.name!;
validatePaddingConstantName(constantName);
final generatedName = toNameForGeneration(constantName);
return generatePaddingWidgets(generatedName, constantName);
}
}
paddinger_generator.dart
Paddinger source code
String generatePaddingWidgets(String paddingName, String constantName) {
return '''
${_addStartComment(paddingName)}
${_addAllPadding(paddingName, constantName)}
${_addOnlyPaddings(paddingName, constantName)}
${_addSymmetricPaddings(paddingName, constantName)}
${_addMissingCombinationPaddings(paddingName, constantName)}
${_addEndComment(paddingName)}
''';
}
Paddinger source code
String _addAllPadding(String paddingName, String constantName) {
return '''
class ${paddingName}AllPadding extends Padding {
const ${paddingName}AllPadding({Key? key, required Widget child})
: super(
key: key,
padding: const EdgeInsets.all($constantName),
child: child);
}
''';
}
Paddinger source code
class MediumAllPadding extends Padding {
const MediumAllPadding({Key? key, required Widget child})
: super(
key: key,
padding: const EdgeInsets.all(PADDING_MEDIUM),
child: child);
}
Paddinger source code
String _addOnlyPaddings(String paddingName, String constantName) {
final onlyPaddingKeys = PaddingDirection.values
.map((paddingDirection) => paddingDirection.asPascalCase);
final onlyPaddingWidgets = onlyPaddingKeys.map((paddingKey) => '''
class $paddingName${paddingKey}Padding extends Padding {
const $paddingName${paddingKey}Padding({Key? key, required Widget child})
: super(
key: key,
padding: const EdgeInsets.only(${paddingKey.toLowerCase()}:
$constantName),
child: child);
}
''').toList();
return onlyPaddingWidgets.join();
}
Paddinger source code
class MediumLeftPadding extends Padding {
const MediumLeftPadding({Key? key, required Widget child})
: super(
key: key,
padding: const EdgeInsets.only(left: PADDING_MEDIUM),
child: child);
}
class MediumTopPadding extends Padding {
const MediumTopPadding({Key? key, required Widget child})
: super(
key: key,
padding: const EdgeInsets.only(top: PADDING_MEDIUM),
child: child);
}
///two more classes: MediumRightPadding and MediumBottomPadding
How can you test the
generated code?
Test the generated code
test(
'GIVEN a valid padding constant name, WHEN validatePaddingConstantName(), THEN it
returns normally',
() {
expect(
() => validatePaddingConstantName("PADDING_MEDIUM"), returnsNormally);
});
test(
'GIVEN a not valid padding constant name, WHEN validatePaddingConstantName(),
THEN an exception is thrown',
() {
expect(() => validatePaddingConstantName("PADDIN_MEDIUM"),
throwsA(isA<Exception>()));
});
Test the generated code
test(
'GIVEN a valid padding constant name, WHEN toNameForGeneration(), THEN a
valid name is generated',
() {
expect(toNameForGeneration("PADDING_MEDIUM"), "Medium");
});
test(
'GIVEN a valid padding constant name with two underscores, WHEN
toNameForGeneration(), THEN a valid name is generated',
() {
expect(toNameForGeneration("PADDING_VERY_LARGE"), "VeryLarge");
});
Test the generated code
test(
'GIVEN a valid paddingName and a valid constantName, WHEN generatePaddingWidgets(), THEN valid padding widgets are
generated',
() {
expect(generatePaddingWidgets("Medium", "PADDING_MEDIUM"), '''
// **************************************************************************
// START Medium
// **************************************************************************
class MediumAllPadding extends Padding {
const MediumAllPadding({Key? key, required Widget child})
: super(
key: key,
padding: const EdgeInsets.all(PADDING_MEDIUM),
child: child);
}
///Other classes here, this line is not part of the real generated code
''');
});
Nice helpful tips
IDE code completion will be able to:
- suggest you all the available Padding classes
- transforms TLMP into TopLeftMediumPadding
Can you generate
whatever you want?
Yes!
Don't limit your
imagination!
Thank you!
Drop a line to info@zest.one
Get in touch with me
https://www.emanuelepapa.dev
We are hiring @ ZestOne

More Related Content

Similar to Supercharge Flutter declarative UI with code generation

Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java DevelopersYakov Fain
 
Behavioural Driven Development in Zf2
Behavioural Driven Development in Zf2Behavioural Driven Development in Zf2
Behavioural Driven Development in Zf2David Contavalli
 
Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and ToolsBob Paulin
 
Developer Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for BeginnersDeveloper Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for BeginnersJiaxuan Lin
 
Dsug 05 02-15 - ScalDI - lightweight DI in Scala
Dsug 05 02-15 - ScalDI - lightweight DI in ScalaDsug 05 02-15 - ScalDI - lightweight DI in Scala
Dsug 05 02-15 - ScalDI - lightweight DI in ScalaUgo Matrangolo
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsAdégòkè Obasá
 
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF SummitOrtus Solutions, Corp
 
Cordova iOS Native Plugin Development
Cordova iOS Native Plugin DevelopmentCordova iOS Native Plugin Development
Cordova iOS Native Plugin DevelopmentJosue Bustos
 
Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Fafadia Tech
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best PracticesYekmer Simsek
 

Similar to Supercharge Flutter declarative UI with code generation (20)

Coding Naked 2023
Coding Naked 2023Coding Naked 2023
Coding Naked 2023
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
 
Android For All The Things
Android For All The ThingsAndroid For All The Things
Android For All The Things
 
Behavioural Driven Development in Zf2
Behavioural Driven Development in Zf2Behavioural Driven Development in Zf2
Behavioural Driven Development in Zf2
 
Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and Tools
 
Wtf per lineofcode
Wtf per lineofcodeWtf per lineofcode
Wtf per lineofcode
 
Developer Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for BeginnersDeveloper Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for Beginners
 
Choose flutter
Choose flutterChoose flutter
Choose flutter
 
Dsug 05 02-15 - ScalDI - lightweight DI in Scala
Dsug 05 02-15 - ScalDI - lightweight DI in ScalaDsug 05 02-15 - ScalDI - lightweight DI in Scala
Dsug 05 02-15 - ScalDI - lightweight DI in Scala
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web Apps
 
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
 
IOC + Javascript
IOC + JavascriptIOC + Javascript
IOC + Javascript
 
appledoc_style
appledoc_styleappledoc_style
appledoc_style
 
Cordova iOS Native Plugin Development
Cordova iOS Native Plugin DevelopmentCordova iOS Native Plugin Development
Cordova iOS Native Plugin Development
 
Extend sdk
Extend sdkExtend sdk
Extend sdk
 
CDI @javaonehyderabad
CDI @javaonehyderabadCDI @javaonehyderabad
CDI @javaonehyderabad
 
Bronx study jam 1
Bronx study jam 1Bronx study jam 1
Bronx study jam 1
 
Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)
 
Excelian hyperledger walkthrough-feb17
Excelian hyperledger walkthrough-feb17Excelian hyperledger walkthrough-feb17
Excelian hyperledger walkthrough-feb17
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 

Recently uploaded

Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 

Recently uploaded (20)

Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 

Supercharge Flutter declarative UI with code generation

  • 1. Supercharge Flutter Declarative UI with code generation Emanuele Papa droidcon London 2021
  • 2. Working at Zest One in Chiasso, Switzerland Who I am? Emanuele Papa, Android Developer Find me at www.emanuelepapa.dev
  • 3. Declarative UI Imperative UI -> Declarative UI Jetpack Compose and SwiftUI Unfortunately, not perfect yet No more XML or UIKit
  • 4. Padding in Flutter Padding( padding: EdgeInsets.all(16.0), child: Text("Hello droidcon!") );
  • 5. What we want - Make the code easy to write - Avoid errors caused by distraction - Minimize code duplication - Make the IDE our best friend - Improve our productivity
  • 6. Looking for improvements Someone else experienced the same struggle Some libraries are available on GitHub
  • 7. It's an improvement, but you still need to add the Padding value manually The missing thing PaddingTop(16.0, child: Text("Hello droidcon!"));
  • 8. Design System Padding No need to add the Padding value manually, it's specified in the class name MediumTopPadding(child: Text("Hello droidcon!"));
  • 9. How to create these widgets?
  • 11. How to use Paddinger? dependencies: paddinger_annotations: [latestVersionHere] dev_dependencies: paddinger: [latestVersionHere] Add these dependencies to your pubspec.yaml
  • 12. How to use Paddinger? Create a paddings.dart file which contains your PADDING_ definitions @paddinger const double PADDING_MEDIUM = 16.0; @paddinger const double PADDING_LARGE = 24.0;
  • 13. How to use Paddinger? Add material or cupertino import Add part directive // ignore: unused_import import 'package:flutter/material.dart'; part 'paddings.g.dart';
  • 14. Start the code generation Now run flutter pub run build_runner build --delete-conflicting- outputs
  • 16. What's the result? class MediumAllPadding extends Padding { const MediumAllPadding({Key? key, required Widget child}) : super( key: key, padding: const EdgeInsets.all(PADDING_MEDIUM), child: child); }
  • 17. Do not add it to your version control system How to use them Just import paddings.dart in your widgets, it also contains all the generated classes created in paddings.g.dart
  • 18. Let's deep dive inside paddinger source code!
  • 19. Paddinger source code Monorepo with 2 projects: - paddinger - paddinger_annotations
  • 20. Paddinger source code ///Annotation used by paddinger to identify PADDING_ constants class Paddinger { const Paddinger(); } ///Helper object for [Paddinger] annotation const paddinger = Paddinger(); paddinger.dart
  • 21. Paddinger source code dependencies: analyzer: ^1.5.0 build: ^2.0.0 source_gen: ^1.0.0 recase: ^4.0.0 paddinger_annotations: ^0.1.1 #local development #paddinger_annotations: # path: ../paddinger_annotations/ dev_dependencies: test: 1.16.8 pubspec.yaml
  • 22. Paddinger source code builders: paddinger_generator: import: "package:paddinger/paddinger.dart" builder_factories: ["paddingerGenerator"] build_extensions: {".dart": [".paddinger.g.part"]} build.yaml
  • 23. Paddinger source code ///Paddinger generator used with [Builder] Builder paddingerGenerator(BuilderOptions options) => SharedPartBuilder([PaddingerGenerator()], 'paddinger_generator'); paddinger.dart
  • 24. Paddinger source code class PaddingerGenerator extends GeneratorForAnnotation<Paddinger> { @override FutureOr<String> generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) { final constantName = element.name!; validatePaddingConstantName(constantName); final generatedName = toNameForGeneration(constantName); return generatePaddingWidgets(generatedName, constantName); } } paddinger_generator.dart
  • 25. Paddinger source code String generatePaddingWidgets(String paddingName, String constantName) { return ''' ${_addStartComment(paddingName)} ${_addAllPadding(paddingName, constantName)} ${_addOnlyPaddings(paddingName, constantName)} ${_addSymmetricPaddings(paddingName, constantName)} ${_addMissingCombinationPaddings(paddingName, constantName)} ${_addEndComment(paddingName)} '''; }
  • 26. Paddinger source code String _addAllPadding(String paddingName, String constantName) { return ''' class ${paddingName}AllPadding extends Padding { const ${paddingName}AllPadding({Key? key, required Widget child}) : super( key: key, padding: const EdgeInsets.all($constantName), child: child); } '''; }
  • 27. Paddinger source code class MediumAllPadding extends Padding { const MediumAllPadding({Key? key, required Widget child}) : super( key: key, padding: const EdgeInsets.all(PADDING_MEDIUM), child: child); }
  • 28. Paddinger source code String _addOnlyPaddings(String paddingName, String constantName) { final onlyPaddingKeys = PaddingDirection.values .map((paddingDirection) => paddingDirection.asPascalCase); final onlyPaddingWidgets = onlyPaddingKeys.map((paddingKey) => ''' class $paddingName${paddingKey}Padding extends Padding { const $paddingName${paddingKey}Padding({Key? key, required Widget child}) : super( key: key, padding: const EdgeInsets.only(${paddingKey.toLowerCase()}: $constantName), child: child); } ''').toList(); return onlyPaddingWidgets.join(); }
  • 29. Paddinger source code class MediumLeftPadding extends Padding { const MediumLeftPadding({Key? key, required Widget child}) : super( key: key, padding: const EdgeInsets.only(left: PADDING_MEDIUM), child: child); } class MediumTopPadding extends Padding { const MediumTopPadding({Key? key, required Widget child}) : super( key: key, padding: const EdgeInsets.only(top: PADDING_MEDIUM), child: child); } ///two more classes: MediumRightPadding and MediumBottomPadding
  • 30. How can you test the generated code?
  • 31. Test the generated code test( 'GIVEN a valid padding constant name, WHEN validatePaddingConstantName(), THEN it returns normally', () { expect( () => validatePaddingConstantName("PADDING_MEDIUM"), returnsNormally); }); test( 'GIVEN a not valid padding constant name, WHEN validatePaddingConstantName(), THEN an exception is thrown', () { expect(() => validatePaddingConstantName("PADDIN_MEDIUM"), throwsA(isA<Exception>())); });
  • 32. Test the generated code test( 'GIVEN a valid padding constant name, WHEN toNameForGeneration(), THEN a valid name is generated', () { expect(toNameForGeneration("PADDING_MEDIUM"), "Medium"); }); test( 'GIVEN a valid padding constant name with two underscores, WHEN toNameForGeneration(), THEN a valid name is generated', () { expect(toNameForGeneration("PADDING_VERY_LARGE"), "VeryLarge"); });
  • 33. Test the generated code test( 'GIVEN a valid paddingName and a valid constantName, WHEN generatePaddingWidgets(), THEN valid padding widgets are generated', () { expect(generatePaddingWidgets("Medium", "PADDING_MEDIUM"), ''' // ************************************************************************** // START Medium // ************************************************************************** class MediumAllPadding extends Padding { const MediumAllPadding({Key? key, required Widget child}) : super( key: key, padding: const EdgeInsets.all(PADDING_MEDIUM), child: child); } ///Other classes here, this line is not part of the real generated code '''); });
  • 34. Nice helpful tips IDE code completion will be able to: - suggest you all the available Padding classes - transforms TLMP into TopLeftMediumPadding
  • 38. Drop a line to info@zest.one Get in touch with me https://www.emanuelepapa.dev We are hiring @ ZestOne