Flutter: Custom Widgets Using Existing Classes
By: Wilson Hadi
Tags: Testing, Flutter, Alertdialog, Dart, Custom Widget

New in Flutter and want to start making custom widgets? This article will give a simple example of making custom widgets while using the classes available from Flutter.

Before we start talking about the Flutter stuff, let’s talk about refactoring.

NOTE: For those who want to just look into the Flutter part, feel free to skip ahead.

What is Refactoring?

“Refactoring is a controlled technique for improving the design of an existing code base.” — Martin Fowler

Refactoring is done by applying small changes to the code design while preserving their behaviour. It is an iterative practice with the goal of reducing bug potentials, reduce code smells, reduce code duplications, improving reusability and maintainability.

Keep in mind that refactoring is NOT changing nor adding functionality

Most of the time, refactoring is closely related to design patterns. This is because you can refactor the code design into already well-known design patterns, which of course is a good especially when working in a larger team. However, let us talk about some of the many basic methods of refactoring your code:

Extract Method

This is when a method or function looks just too long and is most likely doing something that belongs to another method, or can be split into more than 1 method. Always keep in mind that methods should be responsible in only doing 1 thing. Extract the lines of code that don’t belong in a method’s responsibility into a new method.

// Before

method(int a, int b) {

processedA = doSomething(a);

processedB = doSomething(b);



print('result of a: ' + processedA);

print('result of b: ' + processedB);

} // After

method(a, b) {

processedA = doSomething(a);

processedB = doSomething(b);



printResults();

} printResults(a, b) {

print('result of a: ' + a);

print('result of b: ' + b);

}

Extract Variable

This is when a method is too hard to understand. This method takes logic that seem too complicated into a variable, and operates on those variable instead. Keep in mind that the variables should have meaningful names

// Before

method() {

if ((a.toUpperCase().indexOf(indexA) > -1) &&

(b.toUpperCase().indexOf(indexB) > -1) &&

c > 0 ) {

// do something

}

} // After

method() {

isSomething = a.toUpperCase().indexOf(indexA) > -1;

isSomethingElse = b.toUpperCase().indexOf(indexB) > -1;

isCValid = c > 0;



if (isSomething && isSomethingElse && isCValid) {

// do something

}

}

Extract class

This is when a class has unnecessary fields that don’t really make sense for it to be there. This method extracts those fields and creates a new class as a field of the first class.

// Before

class Person {

String name

int areaCode

int phoneNumber getFullPhoneNumber() {

return '$this.areaCode' + '$this.phoneNumber'

}

} // After

class Person {

String name

PhoneNumber phoneNumber getPhoneNumber() {

return this.phoneNumber

}

} class PhoneNumber {

int areaCode

int phoneNumber getFullPhoneNumber() {

return '$this.areaCode' + '$this.phoneNumber'

}

}

There are many more methods of refactoring, here is a pretty complete link to help you learn more refactoring methods:

Implementation in my project

Since I am working mostly in the front-end, most of the refactoring I do is reducing code duplication. In flutter, many widgets can be similar and have many duplicate codes especially when the same widget classes are used, or the same combination of widgets are used. I found a lot of these cases in my team’s code base. Another example is when functions are simply too long when processing data from user input and/or API retrieval.

An example refactoring I did was mostly extract method for refactoring those functions that are too long:

The function above looks so long and clearly has lines of code that do not belong to its responsibility. After refactoring, the code becomes:

Now the function looks much more concise after extracting and creating new functions.

Another example refactoring I did was creating custom widgets. This allows the same structuring of widgets to create, for example, a custom button design, or a custom container (with specific margin, padding, border radius, etc.) to be reused with significantly less code clutter.

Below is an example process of my implementation in creating a custom widget.