Skip to content

artembark/city_info_guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

86 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

City guide app project description

City guide app. Development is in progress.

menu menu menu menu menu menu

video5287743656415992783.mp4

How to build this app

After cloning don't forget to run flutter pub get and flutter pub run build_runner build --delete-conflicting-outputs
Also in order to build this app you need to get an api key from Yandex Schedule Api, Yandex Map Api and add additional run arguments:
--dart-define=API_KEY=your_schedule_api_key
--dart-define=MAP_API_KEY=your_map_api_key

Packages used

Architecture

arch1 arch2

From this source
As in the diagram above, the clean architecture is depicted as a pyramid or a slice of onion when viewed from the top. The clean architecture will divide the Flutter project into 3 main layers, namely:

  • Data & Platform layer
    The data layer is located at the outermost layer. This layer consists of data source code such as consume Rest API, access to the local database, Firebase, or other sources. Also, on this layer, there is usually the platform code that builds up the UI (widgets).
  • Presentation Layer
    The presentation layer consists of the code to access the data of the app from a repository. Also, there is the code for state management such as providers, BLoC, and so on.
  • Domain Layer
    The domain layer is the deepest in the clean architecture. This layer contains the code for business logic applications such as entities and use cases. Each layer depends on the other layers. The arrows on the diagram show how the layers are related. The outermost layer will depend on the inner layer and so on.
    The layer that does not depend on any other layers here is only the domain layer (independent) which is the code for the business logic. That way, the application is more adaptable and dynamic. For example, if we want to change the state management from the provider to BLoC, the migration process will not interfere with the existing business logic.

Yandex Schedule API

It is good to know how one can come to your city and leave it. So you need a schedule service.
Project involves Yandex Schedule Api
Documentation can be found here
Currently project uses two API methods:

  • get schedule between two stations
  • get nearest settlement to current location (geocoder)

Suggests API

In order to simplify entering from and to position for schedule this app uses suggestions API. Settlements name appear as you type letters, suggesting you convenient names. Schedule api also needs to have city codes in request. Suggests api is used for converting human readable city names to codes. This app uses Yandex suggests api

A native splash screen will be shown before flutter app starts.

flutter_native_splash:
  color: "#0B85FF"
  image: assets/images/bird.png

After adding assets run the following command:

flutter pub run flutter_native_splash:create

How it works under the hood

Yandex Map intent

As an example of platform channel this app implements opening Yandex Map with a point to make route to, showing organization card and showing 360 degree panorama.
Documentation to Yandex Map intents is here

To open Android native and iOS native from Android Studio Flutter project go to Tools-Flutter-Open corresponding variant.
Writing custom platform-specific code
How To Call iOS Native Code [2021] Swift Platform Specific Code
How To Call Android Native Code [2021] 1/2 Java & Kotlin Platform Specific Code
For iOS don't forget to add url schemes in Info.plist file

<key>LSApplicationQueriesSchemes</key>
<array>
<string>yandexmaps</string>
</array>

Heavy task isolate computing

The project uses Dio as network requests handler. Dio transformer allows changes to the request/response data before it is sent/received to/from the server. Transformer is used to set jsonDecodeCallback to execute a jsonDecode function in a separate isolate.

// Must be top-level function
_parseAndDecode(String response) {
return jsonDecode(response);
}

parseJson(String text) {
return compute(_parseAndDecode, text);
}

void main() {
...
//Custom jsonDecodeCallback
(dio.transformer as DefaultTransformer).jsonDecodeCallback = parseJson;
runApp(MyApp());
}

Testing coverage

flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html

Config for json_serializable in build.yaml

$default:
builders:
json_serializable:
options:
explicit_to_json: true
field_rename: snake

Android Studio file nesting rules

In Visual Studio Code you can hide dedicated file types in project tree. But sometimes you still need to look inside this files. In Android Studio in oder to keep folder structure clear you can customize file nesting rules and add *.g.dart and *.freezed.dart. Press settings button in the upper right corner of project tree window and select "File Nesting"

menu

Add file extensions separated by the `;`

settings

Auto route

DOC
More DOC (slightly different examples(maybe not up to date))

This app uses AutoRoute for navigation. If you wrap FirstRoute() page content with BlocProvider and use context.router.push(SecondRoute()) for navigating to second page and try to access blocs provided in the first page you will get an error. The second page doesn't know anything about blocs, provided on the first page. In order to access the same bloc instance through multiple pages you can either pass it as a parameter orit is necessary to create nesting routing by creating a wrapper page and implementing BlocProvider in it. So each page on this nested route will have access to this bloc/blocs.
Milad-Akarie comment In a nested route there is no back button in the AppBar by default, so you need to add it manually by providing leading: const AutoLeadingButton()
By returning from a second page with back button press you can wrap the second page with WillPopScope and add events to bloc or execute functions of cubit by writing context.read<MyCubit>().cubitFunction(); or context.read<MyBloc>().dispatch(blocEvent);
Felix Angelov comment
Alternative example implementing AutoRouteWapper

Preload images

In order to show images instantly, without artefacts, you can preload them. Source

To run iOS on a real device

Use flutter run --release

YandexMapKit

Problems with iOS deployment. Fixed with changing target OS version to 12.0 and running this

Also need specify locale YMKMapKit.setLocale("ru_RU")

Icons generator

Use flutter pub run flutter_launcher_icons:main

App name change

From here Open AndroidManifest.xml (located at android/app/src/main)
Android
<application android:label="App Name" ...> // Your app name here
iOS
Open info.plist (located at ios/Runner) <key>CFBundleName</key> <string>App Name</string> // Your app name here
Don't forget to run flutter clean
Can use THIS package alternatively.

Easy Localization

For localization a package easy_localization is used.
Terminal commands:

  • to generate translations:
    flutter pub run easy_localization:generate -S "assets/translations" -O "lib/core/l10n"
  • to generate keys:
    flutter pub run easy_localization:generate -S "assets/translations" -O "lib/core/l10n" -o "locale_keys.dart" -f keys

Generating assets paths

Code generator for assets allowing to get rid of all String-based APIs. The code is generated with build_runner. To explicitly specify output directory add this lines to pubspec.yaml
flutter_gen: output: lib/app/assets

About

City info guide app project.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published