CraftD: An Ideal Solution for Server-Driven UI in Flutter Apps
Many companies are embracing the Server-Driven UI pattern for its flexibility in customizing and updating user interfaces and enhancing user experiences. However, the variety of strategies developers use to implement this pattern can lead to inconsistencies and fragmented solutions. CraftD addresses this issue by offering a unified approach that ensures consistency across platforms. In this article, I will show you how to integrate CraftD into your Flutter application.
📚Add CraftD library
First, we need to add CraftD as a dependency to our project:
flutter pub add craftd_widget
🎯 Define your data source
Your data source could be a server, local database, or another option. In my case, I’m loading a JSON file from the assets directory:
class LocalDataSource {
Future<List<SimpleProperties>> loadProperties(BuildContext context) async {
var value = await DefaultAssetBundle.of(context)
.loadString("assets/uiElements.json");
List<dynamic> list = jsonDecode(value);
return list.map((properties) {
return SimpleProperties.fromJson(properties);
}).toList();
}
}
At the uiElements.json
file, I have a JSON where I define some components:
[
{
"key": "CraftDTextView",
"value": {
"text": "Chuck Norris",
...
}
},
{
"key": "CraftDTextView",
"value": {
"text": "X",
...
}
},
{
"key": "CraftDTextView",
"value": {
"text": "Bruce Lee",
...
}
},
{
"key": "CraftDButton",
"value": {
"text": "Fight!",
...
}
}
]
Basically, we have three text elements (Chuck Norris, X, Bruce Lee) and a button labeled ‘Fight!’.
It is very important to highlight the LocalDataSource
exposes the type List<SimpleProperties>
.
🏗 Specify your UI Builder
In my home screen, I am creating an instance of LocalDataSource
:
class _MyHomePageState extends State<MyHomePage> {
List<SimpleProperties> simplePropertiesList = [];
final LocalDataSource localDataSource = LocalDataSource();
final craftDBuilderManager = CraftDBuilderManager();
@override
void initState() {
super.initState();
...
loadProperties();
}
...
It’s crucial to create an instance of CraftDBuilderManager
, as this builder will take the list of SimpleProperties
from your data source and convert them into widgets. Now, let’s take a look at the loadProperties
method:
void loadProperties() async {
List<SimpleProperties> properties =
await localDataSource.loadProperties(context);
setState(() {
simplePropertiesList = properties;
});
}
The loadProperties
method fetch the simple properties, and update the uiState
with the result. After that, the simplePropertiesList
will trigger the builder definition:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: ...
body: Center(
...
child: CraftDynamic(
simplePropertiesList: simplePropertiesList,
craftDBuilderManager: craftDBuilderManager,
onAction: (actionProperties) {
...
},
..
}
The CraftDynamic
will take in both the CraftDBuilderManager
and the simplePropertiesList
to generate the widgets using the simplePropertiesList
as input.
🤔 Conclusion
CraftD is an impressive library, and what I liked most about it includes:
- Flexibility, allowing integration with various data sources;
- Ease of use, with no need for UI layer adjustments;
- Comprehensive documentation with well-organized examples;
- Standardization across different frameworks (native iOS, native Android), making it easier for teams to collaborate and speak the same language.
🔗 Useful links
- Sample repository
- Video about CraftD
- CraftD repository
- Article about CraftD for all platforms