Flutter: Making the switch

Flutter: Making the switch

After learning Android development, I knew that native code — Java, now Kotlin — would be the way I would proceed going forward. I'd heard of all the cross-platform options but they never sounded good to me. I always felt as if they were subpar options; the apps I'd seen with them always "looked" like they came from cross-platform code (whatever that means).

Basically, I was super judgey.

There's always been a need for them, though. One problem I continuously faced because I only did native Android code was that if I ever thought of a business opportunity or side project, I would only be able to do the Android code. If I wanted to potentially offer an iOS app, I'd have to either learn to do it by hand or hire someone else.

But I stuck to my guns and never went through with any ideas that came to mind.

At my job, I ended up being the only mobile developer in house. We have an iOS contractor who takes care of our two primary iOS apps, and I take care of the Android apps. We eventually acquired another company, one that had an Android and iOS app.

But it was written with Flutter.

"Well, f*."

I'm an eager learner, honestly. I started dabbling in Python some years back because it worked for AWS and it's been my rando language of choice since then. I don't really "know it" but I know enough to get by.

So I dived in to learn Dart and what I could do with Flutter.

Why was I so stubborn!?

I think Dart and Flutter are easy to learn, but there's definitely a learning curve. One of the first things I had to learn was how to build out a screen.

Building a layout

My thoughts on Flutter's layouts have changed since I was first introduced. In the beginning, I was a bit confused but learned how to just deal. I considered it just one of those things in a programming language that doesn't need a true explanation. Just learn it that way and move on.

However now that I've spent more time with it (and Android has announced Compose), I see Flutter's layout a bit differently. I used to think they were drastically different from the XML layouts used in android.

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/white">

    <TextView
        android:id="@+id/hello_world"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
                android:layout_gravity="center"
        android:text="Hello World!"/>

</LinearLayout>

In a basic layout, we'd have our main ViewGroup, something like a LinearLayout or — my favorite default — a ConstraintLayout. To show "Hello World!" we throw in a TextView and tell it to be centered within the view. Done.

When I learned how to do this in Flutter, I was puzzled. This was some weird nested hierarchy that was done in Dart. They aren't separate files!?

Say what?

In flutter, I have to return a Widget in a build function. In that function, I deeply nest my Widgets in some strange hierarchy where each Widget is a child of another, and I apply certain configurations to each to change how to look and are positioned.

Oh, wait. It's exactly like XML.

@override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      alignment: Alignment.center,
      child: Text("Hello !"),
    );
  }

That's it, technically. I can make it more complex by adding a Scaffold and a SafeArea, but this is honestly pretty simple. In fact, it's arguably simpler than the XML.

When you first create your Flutter project in Android Studio, they give you an amazing starting layout, which includes a Scaffold. Without looking up the definition, I'm going to do my best to explain what that is.

A Scaffold in Flutter is that basic UI layout that has the possibility to have a toolbar at the top, with bottom navigation and a floating action button. You could probably do without and make it all yourself. That's actually what I tend to do in Android layouts, adding what I need and aligning it properly in a ConstraintLayout. In Flutter, the Scaffold probably the best way to go about it. And it's super easy!

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

One thing that still takes some getting used to is that you don't really use Strings all "willy nilly" like I'm used to everywhere else. In Flutter, you almost always wrap them in a Text widget. In fact, most widgets that have a place for text only require a Widget.

This means that you can do some crazy things, all out of the box. For example, in the AppBar, the title parameter in Android would probably be a generic String. In Flutter, however, it takes just a Widget. Text is a Widget, but so is Container... or another SCAFFOLD!

Please don't put another Scaffold there.

But this means that if I wanted to add a subtitle, I can customize the way the title is shown, adding a Column (another Widget) with room for them both. Or perhaps I want just an image there. The possibilities are pretty much endless.

Again, please don't put another Scaffold there.

Your main arsenal

There's a million Widgets out there, but here are the ones I use constantly for my layouts.

Text

For all your String needs. You can style them by adding a TextStyle to it.

Row & Column

They are the literal building blocks of tables. If you're at all familiar with HTML, these two are used the same. (I think? The last time I really built a website was when Pokemon was new and Pokemon websites dominated the internet.) Rows are horizontal, Columns and vertical. Both take a list of Widgets, including other Rows and Columns if you need them.

Visibility

This was a weird one to learn about. In Android, Views have a visibility value that can be set. In Flutter, that wasn't there. But you can wrap them in a Visibility widget and set the flag accordingly.

Center

Similar to Visibility, this was a bit of a learning curve.

MenuItem

This might be due to the way my company's app is set up, but I use this little thing everywhere. Icon to the left, title, with a potential subtitle should I need it? EASY.

StreamBuilder

Sigh. I won't go in depth on this Widget in this blog post, but I both LOVE this Widget and hate it. I'm new to the BLoC pattern, where Sinks and Streams are used heavily, and this thing relies on Streams. I'm going to eventually write up my thoughts on the BLoC pattern and how to best utilize it, but until then the Flutter website has an amazing page on this Widget.


That's all I'm going to get into today. Nothing too specific. I really just wanted to get the people who've been on the fence about trying it. Try it. It's super easy and opens the doors for so many possibilities.

I'm still a diehard Android native guy, though. lol