Krzysztof Dziedzic, Author at Mood Up team - software house
Flutter in programming

What is Flutter and how does it work

What is Flutter?

Flutter is Google’s UI toolkit for building natively compiled applications for mobile, web, desktop, and embedded devices with a single codebase. It was released on 4th Dec 2018 and has been growing since then. Today it has over 2 million users, and that number still keeps getting bigger.

To build apps with Flutter, you need to know the Dart programming language. Dart is an object-oriented programming language that aims to be as fast as possible on all platforms that use AOT (ahead-of-time) compilation with native machine code. In this article, we will go through the basics of Flutter. You will find out are the advantages of using it and how it is different from similar solutions, like React Native.

Flutter basics

Views

Flutter uses the declarative approach to build the views. This means that you describe the effect you want to achieve. For instance, if you want to display a list with Text, ProgressIndicator,andButton, you wrap these widgets in the Columnwidget. No need to write any additional code that would handle the rendering of UI elements.

1_code (Column Widget)

This results in:
column animation

 

Widgets

It’s a good moment to establish what exactly widgets are. They are fundamental building blocks in the Flutter world. Widget is a part of the User Interface. It could be either visible, like buttons  or  form fields, or invisible and serving to define the layout structure, such as column , row , or container.  It’s all about nesting widgets inside other widgets and building more complex UI parts.

Type of Widgets

There are two types of Widgets – stateless and stateful . A stateless widget is a widget that does not have its state – which means that it is immutable. It cannot be changed during the app runtime. A stateful widget, on the other hand, can hold a state and is dependent on it. Every time the state changes, the widget is rebuilt with the new state value.

Make it faster with Flutter

Built-in widgets

One of the biggest advantages of Flutter is that you get plenty of out-of-the-box components. That means you don’t have to bother with tons of boilerplate code to make something look cool. If you want to implement some fancy, animated stuff like a collapsible app bar, you might just discover that there is a widget that lets you do that with a few lines of code.

Hot reload

Another feature that can speed up the development process is a hot reload feature. It works by injecting the updated source code straight into a running Dart Virtual Machine. In other words, the changes that you make are applied while the app is running. No more rebuilding the whole project just to see an updated text or color!

One codebase, multiple platforms

As we mentioned before, Flutter is about writing one codebase that can be delivered to different platforms. Currently, it supports mobile (Android and iOS), web, desktop, and embedded devices. This means you can build the app on the platform of your choosing.

External packages

Nobody likes reinventing the wheel. If you are working on a particular solution and you feel that you have seen something similar before, you should go to https://pub.dev/ to see if there is a package for that. There you can find solutions for various problems that have been previously experienced by other programmers. Need to work with the SqlLite database? Just grab sqllite package, import it to your project and start using it. It is that simple.

Mixing Flutter with native solutions

Imagine a situation when you need to create a custom element. There is no widget or package for that (highly unlikely!), and you need to trigger some native code to achieve it. Is it possible to run native Android or iOS code from the Flutter app level? Short answer, yes!

It is not an everyday treat to run a native code, because there is usually good Flutter-level support out there. But if for some reason you have to do that, you absolutely can!

Running native code

Flutter uses a message-passing style method to communicate with the native API. You need to create a MethodChannel object on the client (Flutter app) side. Then you can set a handler for messages from this channel on the host side (Native app). This channel allows clients and hosts to communicate with each other.

Let’s take a look at a real-life example. We will call an Android MainActivity method from the Dart code and get a result. First of all, we need to make a MethodChanel on the Flutter side. Make sure it has a unique name.

2_code MethodChanel - client side

Next, we create a method in MainActivity class and set a handler for our MethodChannel:

3_code - host side

When all this is done, we can call our native method from the Flutter app:

4_code - Calling a method on client side

The above example shows how to do that for Android, but the method is similar for iOS.

Displaying native view

Sometimes you may want to use a native view in your Flutter app – for example, Google Maps from Android and iOS. There is a Platform Views feature that allows you to do just that. By using it, you can write native views that need to touch a native code, and then just put it straight into your widget tree.

Displaying modes

Currently, Flutter can render Android native views by using Hybrid Composition or  Virtual Display.

With  Hybrid Composition , a native android.view.View  will be added to the view hierarchy, which means full support for accessibility or keyboard handling.

On the other hand, with  Virtual Display, the native view will be rendered simply as a Texture and it will not be a part of the view hierarchy. It might cause some issues with interactions such as handling a keyboard.

When it comes to performance, there are a few trade-offs. Generally speaking, Virtual Display is more efficient but also more limited than Hybrid Composition.

iOS uses only Hybrid Composition, so the native UIView  is appended to view hierarchy.

How Flutter is different from similar solutions like React Native

React Native and Flutter have a common goal – to let you deliver an app to multiple platforms by using a single codebase – but the difference lies in how they try to reach it. Here are a few basics differences:

Compilation

With Flutter, the application is compiled ahead of time into a native code, which results in better performance.

On the other hand, React Native uses the JS bridge as a mediator between the native code and the JavaScript code. The code written in JavaScript has to be properly translated into a native code – and vice versa. With Flutter, there is no middleman.

Rendering

The way the app is rendered on the mobile device screen is the biggest difference between Flutter and React Native.

React Native uses JS Bridge to translate JavaScript code into a native code, which means that RN uses native components. If you use the <Button>component, JS Bridge will translate that into a platform-specific native button. Broadly speaking, React Native is a kind of wrapper on top of the Android/iOS native components.

The Flutter way of drawing your app is radically different. Instead of using native components, Flutter draws them on a screen canvas from scratch, using a very efficient 2D graphics library – Skia. It owns and controls every pixel on the screen. That is why it is usually more efficient than the competition.

The result can be either positive or negative, depending on the point of view. Because Flutter does not rely on native components and draws everything by itself, your app will look the same on every platform and every OS version! Your Flutter app should look and behave the same on Android 5 and 12. It also means that every component will work identically everywhere. With RN, on the other hand, the situation that components have some attributes that are working only on Android or iOS is quite common.

On the screenshots below you can see the same Flutter app running on Android 11 and Android 4.1:

Android 11Android 4 app

 

As you can see, the app is using Material Design, which was created in 2014. Android 4.1 was released 2 years earlier, in 2012– so it does not have any native support for Material Design components. Flutter can still handle that because it renders every pixel by itself.

Pre-built components

As React Native is a kind of wrapper over native UI elements, it provides only basics components. With Flutter, you have access to a rich widgets catalogue. Those are not just simple elements (like buttons) but even more powerful structures, like animated app bars, bottom bars, expandable views, and much more. If you want to learn more, see the widget catalog.

Summary

Flutter has become quite popular over the years. It allows you to create for various platforms by using the same codebase and keep a native performance. A lot of built-in widgets are waiting to help you create beautiful apps.

All these things make Flutter a framework that you cannot simply ignore.

If you want to learn more, look at the official Flutter website.

mood up android

What is Jetpack Compose and why do we need it?

Jetpack compose is a modern Android UI toolkit introduced by Google. It simplifies the app development process and speeds it up. With Jetpack Compose, you can write less code compared to the current view building approach – which also means less potential bugs. There is one more great thing about it – it uses Kotlin. If you have been using React or Flutter, you will probably be familiar with the concept and find many similarities.


How does it work?
 

A main building block of Compose is the Composable function. It emits a part of the user interface. Building with Compose is about nesting the Composable functions in each other.

Zrzut ekranu 2020 12 12 o 20.06.13
This example shows a simple usage of Compose. As you can see, four Composable functions are used: Column– a built-in Composable, which renders its children in the column order, and Text, which displays a given text on the screen.

 

The declarative approach

Jetpack Compose is built upon a different programming paradigm. It uses a declarative paradigm. To put it shortly, it means that you have to change your way of thinking from: “How to do something” to “What goal I want to achieve”. In a declarative way of programming, you try to describe an expected result instead of describing every step to achieve the goal. In the previous example we simply said “I want to have a column with three texts inside” – and that is all. We don’t need to write any extra code that tells the app how to deal with the items inside the column.

In the current imperative approach, things are a bit more complicated. To render a list of elements, RecyclerView is used. It is a component that helps efficiently display large sets of data. The problem is that each RecyclerView needs an adapter, each item on the list needs a ViewHolder, and so on. An adapter is a place where programmers have to describe how RecyclerView is going to render each element. And if we want to render different types of data, it can be a little messy. For instance, if you want to display text, image, and your custom extended view, you have to write a logic to tell the RecyclerView how to do that. As you can see, it’s beginning to look a little complicated and it’s the exact opposite of the Jetpack Compose and the declarative approach. After all, we only want to create a list with some elements inside. With Compose, it is simple as:

 

jetpack2

 

Jetpack Compose ❤️ Kotlin 

One of the greatest advantages of Jetpack Compose is that it uses Kotlin. What does it mean for you? Well, for example, you can use all Kotlin structures directly in your view code. You can use If statements to choose what should be rendered, and you can use loops to display a view multiple times. You can also use functional methods like filter, map, and many others.

 

image1 1


As the picture above shows: it is really simple to choose what should be displayed, depending on the data set state. If it is empty, show a text saying “No data to display”, if it is not, map the data set elements to Composables and display those in a column.

 

The state

Updating a view is a crucial task of every single application. It’s hard to imagine the app which shows you the same data all the time. To update a view in Compose, we need to rebuild Composable functions with different sets of arguments.

This process is called recomposition. The question is “How does a Composable function know when to rebuild itself?”. The answer is – because it can have a state

The state is a value, or multiple values, assigned to a Composable function. Whenever the value is changed, it triggers a recomposition process and our composable function will be rebuilt with a new state value.

 

jetpack4

 

In this example code, we can see one state value – counter. The value of the counter is displayed using the Text Composable. Every time the state is changed, this composable is rebuilt with a new value assigned to the counter variable. In Button’s onClick method, the counter state value, which performs the decomposition process, is incremented, and a new value is displayed with Text.

 

jetpackgif

 

Pagination with Compose

Let’s take a look at a real example that shows how Compose can speed up our work and make it much easier. We are going to compare two solutions for one problem – pagination. We are going to use the current view building solution and Jetpack Compose. 

 

What does pagination mean?  

Pagination is a process of dividing a big data set into smaller chunks. It is useful when we don’t want to serve all data at the same time. It could seriously harm our app performance. The Facebook app is a perfect example – usually, when using the Facebook app, you are scrolling your wall and reading new information. Have you ever reached the end of it? Probably not. It seems endless, which means that there is a huge amount of data to display there. Imagine what would happen if we got all that data at once – it would be an overkill for our device. This shows that your Facebook wall uses pagination. The data is fetched in smaller chunks and displayed on the screen. When you are about to reach the end of the current chunk, a new one is obtained from the backend – and so on.

I want to show you how easy it is to implement pagination when using Compose, compared to the current approach. First of all, let’s see what we need to support pagination when using the current view building methods:

  • RecyclerView – responsible for displaying the data
  • Adapter – displaying logic
  • ViewHolders – keeping views references not to use findViewById() each time to obtain them. It would be really costly.

Usually, we want to somehow indicate that data is being fetched. For instance, we might want to show a progress bar as the last element of the list. With the current approach, it is a slightly complicated task. You have to put a new element into your data set and force the RecyclerView to render it as a progress bar.  There are many ways to achieve that. Usually, you end up with a lot of new code. Each new view type makes your adapter more complicated. With Compose, implementing pagination is really simple – it only takes a few lines of code! 

Let’s have a look:

jetpack5

 

We can see a ComicsResultSection composable here, which is responsible for displaying our data. The data set that should be displayed is passed as an argument – data. By using a LazyColumnForIndexed Composable, we can present our data as a list. LazyColumnForIndexed is an equivalent of RecyclerView –it renders only the data that is visible on the screen. Additionally, LazyColumnForIndexed gives us information about the currently rendered objects and their indexes. By using the index, we can simply check if the currently rendered object is the last in our dataset. If so, we can simply trigger the data fetch method and display a progress bar as the last element of our list. And this is it. No adapters and complicated logic necessary – we simply say what we want to see on the screen.

 

Summary 

Jetpack Compose is a promising and powerful modern UI toolkit that you definitely should keep an eye on. If used correctly, it can speed up the development process and reduce the size of the app. Moreover, with Compose you write less code – which, potentially, means fewer bugs. Happy coding 🙂

If you want to learn more, see the official Compose website:
https://developer.android.com/jetpack/compose