Project Miniclient — Application layer

Oleksandr Leushchenko
Tide Engineering Team
3 min read4 days ago

That’s the last part of the Miniclient tutorial. If you missed the beginning, you may want to check the introduction first.

Congrats, you’ve come a long way, and now we are in the very last part of the Miniclient implementation! From one point of view, that will be the most important part as we will be talking about the application itself. On the other hand, the application should be just a “glue” between features, it should not be smart, and its responsibility is mostly to delegate the work to other components.

Firstly, let’s make it convenient to run the application. If you are using VSCode, create a “.vscode/launch.json” file with the following content:

{
"version": "0.2.0",
"configurations": [
{
"name": "miniclient",
"cwd": "app/miniclient",
"request": "launch",
"type": "dart",
"toolArgs": [
"--dart-define", "MARVEL_PRIVATE_API_KEY=<put your key here>",
"--dart-define", "MARVEL_PUBLIC_API_KEY=<put your key here>"
]
},
{
"name": "miniclient (profile mode)",
"cwd": "app/miniclient",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "miniclient (release mode)",
"cwd": "app/miniclient",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}

That allows you to run the application from any place in the project.

Open the pubspec.yaml file located in the root directory of your project. Add any necessary dependencies for your modules under the dependencies section:

name: miniclient
description: Miniclient study app
publish_to: 'none'

version: 1.0.0+1

environment:
sdk: ^3.2.0
flutter: ^3.16.3

dependencies:
api_client:
path: ../../utility/api_client
tide_design_system:
path: ../../utility/tide_design_system
flutter:
sdk: flutter
marvel_characters:
path: ../../feature/marvel_characters
tide_monitoring:
path: ../../utility/tide_monitoring
tide_di:
path: ../../utility/tide_di

dev_dependencies:
tide_analysis:
path: ../../utility/tide_analysis

flutter:
uses-material-design: true

Let’s start with DI initialization. Each feature and utility package has its own initializer. Most packages declare factories that will be used for instantiation lazily. At Tide, we tend to make features initialize themselves, however, let’s simplify the implementation and make the app call these initializers.

Create a file “lib/src/di/di_initializer.dart” with the following content:

import 'package:api_client/api_client.dart';
import 'package:marvel_characters/marvel_characters.dart';
import 'package:tide_monitoring/tide_monitoring.dart';
import 'package:tide_di/tide_di.dart';

Future<void> initDi() => initializeDIContainer([
..._utilityDIInitializers(),
..._featureDIInitializers(),
]);

List<TideDIInitializer> _utilityDIInitializers() => const [
MonitoringDIInitializer(),
ApiClientDIInitializer(),
];

List<TideDIInitializer> _featureDIInitializers() => const [
MarvelCharactersDIInitializer(),
];

The next step is to call this function. For that, let’s create a widget that would be responsible for initialization.

Create a “lib/src/presentation/boot_page.dart” file with the following content:

import 'package:tide_design_system/tide_design_system.dart';
import 'package:flutter/material.dart';
import 'package:marvel_characters/marvel_characters.dart';
import 'package:miniclient/src/di/di_initializer.dart';

class BootPage extends StatefulWidget {
const BootPage({super.key});

@override
State<BootPage> createState() => _BootPageState();
}

class _BootPageState extends State<BootPage> {
final initialization = initDi();

@override
Widget build(BuildContext context) => FutureBuilder(
future: initialization,
builder: (context, shapshot) {
if (shapshot.connectionState == ConnectionState.done) {
return const MarvelCharactersPage();
}
return const Loading();
});
}

Now, modify the application and make the “BootPage” a home for the app. Change “lib/main.dart” as follows:

import 'package:tide_design_system/tide_design_system.dart';
import 'package:flutter/material.dart';
import 'package:miniclient/src/presentation/boot_page.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) => MaterialApp(
title: 'Miniclient',
theme: miniclientThemeData,
home: const BootPage(),
);
}

The app is ready! Now, you may run the app.

Bonus exercise

  1. Sometimes initialization may fail. Handle this case.
  2. Handle the case when initialization takes too long.
  3. What benefits you may get by replacing “--dart-define”s with “--dart-define-from-file”? Consider the refactoring.

Conclusion

It was quite a challenge and we hope you learned something new. If you found a misprint or have a proposition for improvement, let us know — mobile@tide.co.

About Tide

Founded in 2015 and launched in 2017, Tide is the leading business financial platform in the UK. Tide helps SMEs save time (and money) in the running of their businesses by not only offering business accounts and related banking services, but also a comprehensive set of highly usable and connected administrative solutions from invoicing to accounting. Tide has 600,000 SME members in the UK (more than 10% market share) and more than 275,000 SMEs in India. Tide has also been recognised with the Great Place to Work certification.
Tide has been funded by Anthemis, Apax Partners, Augmentum Fintech, Creandum, Salica Investments, Jigsaw, Latitude, LocalGlobe, SBI Group and Speedinvest, amongst others. It employs around 1,800 Tideans worldwide. Tide’s long-term ambition is to be the leading business financial platform globally.

LinkedIn

--

--