First Glance at Flutter from an Android Native App Developer

30 Jan 2019, by Weiyi Li

I made my decision to try Flutter last December after I saw the demo App "[The History of Everything](" at watching the Flutter 1.0 released video on YouTube, the animation was amazing, I am so touched. As an Android App developer with several years of experience, I am most interested in two questions: - How can Flutter simplify development and make developers' lives easy? - Are there mature Android App solutions that are Flutter-equivalent? The most effective way to learn is coding. So I started to convert few pages of an Android App I am working on to Flutter. The App is a typical List - Detail App contains several key points: # Login Page # List Page # Detail Page +---------------+ +---------------+ +---------------+ | | |[Tab1]2.3[Tab4]| | Image | | [Logo] | |---------------| | Title | | | | item0 | | SubTitle | | [ name ] | => | item1 | => | Body......... | | [ password] | | . | | ............. | | | | . | | | | Login | | . | | | | | | item(n) | | | +---------------+ +---------------+ +---------------+ During this process, I learned a couple of things: - how to build a screen. - how to build a tab navigation view. - how to build a list view. - how to navigate and pass data between screens. - how to restore data during screen rotation. - how to make http request. The following screenshot is the login page which is written in Flutter runs on both iOS and Android: ![](Flutter-eb2b6ba2-efd8-4c34-a45c-932beea5d3cc.png) > BTW: Flutter society provides a lot of resources to learn, the official docs, demo Apps, YouTube channel, Medium articles. I will attach them at the end of this article. ## How to Build a Screen: Screens are Just Widgets ---- As an Android developer, we might have the same experience in development: - (phase 1) Use Activity as a screen at the very beginning; - (phase 2) Then use Fragment as a screen, Activity is just used to host Fragments. We might also struggle with the 2 LifeCycles of Fragment, the nested Fragments backstack, the screen rotation, the navigation between Fragments and Activities. Fortunately we have tools to simplify these problems, like ViewModel, LiveData, Data-binding, Navigation Graph & Controller, etc. Flutter, as a new thing, seems to have no such historical burdens. Flutter claims that > Everything’s a Widget []( **So does Screen**. The following codes snippet builds a simple screen which contains an ActionBar and a Text. The full code contains a `StatefulWidget` which maintains state that might change during the lifetime of the widget, the state won't lost when rotate screen. ```dart Scaffold( appBar: AppBar( title: Text('Welcome to Flutter'), ), body: Center( child: Text('Hello Flutter'), ) ) ``` ## UI as Code: All in One Place ---- You might have realized that to build a screen all by codes is totally different from using XML & visual designer tools. Then you probably questioned how can we build a complicated screen without XML & visual designer tools? It happens to me as well at the very beginning but after writing few pages it has changed my mind and I start to like it because the view logic is all in one place instead of multiple places like Fragment, BindingAdapter, Layout xml, etc. However, All in One Place means a lot of UI codes and might be deeply nested syntax: ```dart ) ]), )) ], ), ), ], ), )); } } ``` But we can get rid of the nested syntax if we follow some rules: > (1). Name subexpressions instead of `return A(B(C(D(), E())), F())`. This turns the widget tree inside out, syntactically. (2). Extract some meaningful pieces… Pieces? Widgets! Flutter widgets are all about composition and reuse. Further reading [Out of Depth with Flutter by Mikkel Ravn]( ## How to Navigate and Pass Data Between Screens ---- In Flutter, **Screens are Just Widgets,** we can just simply pass data to the constructor of the destination widget: ```dart // Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(todo: todos[index]), ), ); ``` Just a few lines of codes, that's it, fairly straightforward. No Intent, no Fragment Arguments, no Parcelable, no startActivity, no fragmentTransaction, no need to know so much details behind Activity and Fragment. ## How to Build a List View ---- ```dart // ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return ListTile( title: Text('${items[index]}'), ); }, ); ``` Just a few lines of codes, no adapter, no item view-holder, no attaching adapter to list view. Further reading: [Flutter ListView and ScrollPhysics: A Detailed Look — Exploring the ListView Widget and its Features in Depth]( ## How to Build a Tab Navigation ---- It's quite easy to implement tab navigation in both Material and Cupertino, just simply create the tabs and content for each tab, then set to TabController widget. Further reading [Working with Tabs]( ## Http & Async ---- It's the common practice to use Retrofit + Gson/Moshi + Data Class + Rx/Coroutines to implement API in nowadays. Are there any equivalents in Flutter? - Json serialization: Flutter provide two ways to serialize Json: manually using [dart:convert]( lib, or automatically using code generation libraries [json_serializable]( Further reading: [JSON and serialization]( - Fetch data from remote: Flutter provide `http` package for this work. Further reading: [Fetch data from the internet]( The following codes snippet shows how I implement the login API in Flutter: ```dart /// api.dart ////////////////////////////////////////////////////////////////// abstract class Api { Future login(String email, String pwd); } /// user.dart ///////////////////////////////////////////////////////////////// part 'user.g.dart'; @JsonSerializable() class User { @JsonKey(name: 'id') int id; @JsonKey(name: 'name') String name; @JsonKey(name: 'email') String email; @JsonKey(name: 'auth_token') String authToken; User(,,, this.authToken); factory User.fromJson(Map json) => _$UserFromJson(json); Map toJson() => _$UserToJson(this); } /// repos.dart //////////////////////////////////////////////////////////////// @override Future login(String email, String pwd) async { final response = await kApiLoginEndpoint, headers: { 'Content-Type': 'application/json', }, body: jsonEncode({ 'email': email, 'password': pwd }), ); if (response.statusCode == 200) { return User.fromJson(json.decode(response.body));; } else { throw ApiException(response.statusCode, response.reasonPhrase); } } /// login_page.dart /////////////////////////////////////////////////////////// void _login(String name, String pwd) { repos.login(name, pwd) .then((user) { print("Login succeed: $user"); }).catchError((e) { print('Failed to login: ${e.toString()}'); }); } ``` The codes above are not well polished and have boilerplate codes. I still have some questions like: - How to log requests and responses? - Is there Retrofit's method(get, delete, post, put) annotations equivalent in Flutter? - How to intercept requests or responses to handle network status, API error, oAuth, header centralized? - How to implement type adapter factory? say if all the API response payloads are wrapped with `data`, like `{ "data": { ... } }` - How to chain APIs like RxJava `flatMap`? I found a 3rd package [dio]( > is a Http client for Dart, supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout etc. I am not sure if it meets all the requirements but just give it a try. ## Animation ---- I cannot say for sure, but Flutter animation looks quite simple at my first glance, compared the Hero animation in Flutter with the equivalent shared element transition animation in Android, just simply wrap the widgets with a `Hero` widget and set with the same tag, that's it! (As you see, "Everything’s a Widget" comes again). ## Dart VS Kotlin ---- Dart doesn't have data class, sealed class, extension function, when expression, lack of null-safe types,... which Kotlin has, it's a pain, however, as a Java Dev, we know that language is just a tool, some fine to use, some not. ## Others ---- - [Display images from the internet]( Flutter has [cached network image]( package, something like Picasso in Android. - [Internationalization and Localization Facilities]( Flutter provide a built-in package for it, including message translation, plurals and genders, date/number formatting and parsing, and bidirectional text. - Depend Injection: not tried yet :( ## How to learn ---- In Flutter, everything’s a widget. Flutter also provides a ton of widgets, to be honest, I almost get lost in composing widgets, but don't worry, there are several sample Apps that show the widget catalog: [Flutter Gallery](,[Flutter Catalog](, [Flutter Go]( [Flutter Widget of the Week]( on YouTube contains a list of one-minute lovely videos showing how to use these widgets. [Search "Flutter cheat sheet" on Google]( you will get articles which are short, sweet and simple with loads of visual examples. [Flutter Codelabs]( provides a guided, tutorial, hands-on coding experience. [The official Flutter documentation]( is the most important, **Get started** part guide you set up the dev environment, **Cookbook** part contains recipes that demonstrate how to solve common problems while writing Flutter apps, each recipe is self-contained and provides complete code and running results in image or gif. ## Summary ---- Flutter gives me a quite different experience compared with Android App development. I am not sure if it's the future, but just give it a try. You will probably also find different things.

Cookies help us deliver our services. By using our services, you agree to our use of cookies.