Students who want to pit flutter are worried about nested hell. However, I have been using Flutter for almost a month and found that if flutter is used properly, nested hell can be avoided. I summarize 5 methods.
Method 1: Appropriate use of “higher-order components”
Flutter official document without the concept of “high order component”, I said here “high order component” refers to the basic components of the built-in components, if pure use basic components to build the UI, the nesting level will be a lot of, we should understand the built-in all kinds of “high order component”, and don’t be afraid of “high order component” inflexible, want to know, The child, title, leading, and other attributes of a component can be assigned to any other component, and “higher-order components” can be extended as well.
Example 1: Use ListTile instead of Row+Container
ListTile is a three-column layout component. If you need a three-column or two-column layout with a fixed width at both ends and an adaptive width in the middle, you can use it directly instead of using Row+Flex+Container.
return ListTile(
leading: CircleAvatar(
// Avatar radius
radius: 25.NetworkImage, AssetImage project bundle, FileImage Locally stored images
backgroundImage: NetworkImage('${mModel.headurl}'),
),
title: Text(
'${mModel.nick}',
style: TextStyle(letterSpacing: 0, color: Colors.black, fontSize: 14),
),
subtitle: Text(
'${mModel.decs}',
style: TextStyle(
letterSpacing: 0, color: Color(0xff666666), fontSize: 10),
),
trailing: mFollowBtnWidget(mModel, i - 1));Copy the code
Example 2: Use RichText instead of Text
import '.. /constant.dart';
RichText(
text: TextSpan(
text: 'Here's the title.',
style: Constant.SUB_TITLE
children: <TextSpan>[
TextSpan(
text: 'Here's the link',
style: Constant.LINK,
TextSpan(
text: 'Fade here',
style: Constant.MUTE_TEXT,
],
),
)
Copy the code
Example 3: Use SliverAppBar instead of AppBar
SliverAppBar is an AppBar with a banner at the top and the banner can slide up and down. If you implement something like this yourself, you have to write a lot of nested and scrolling events. How to use it can be seen in the official documentation.
In short, corresponding to the official component, we should understand thoroughly, do not write a long time of code, the original is the official implementation of the component, waste of time not to say, but also increase the nesting level.
Method 2: Encapsulate custom components
Encapsulation is available in most languages and frameworks, and as you all know, there are a few things to note here:
Components suitable for encapsulation:
- At the top of the AppBar
- Thumb up button
- Share button and share button group (such as wechat share, QQ share)
- The person’s image
- Common home buttons, default buttons (similar to buttons in vUE’s Vant component library)
- Loading animation
- Dialog dialogue window
- Commonly used text with color and size attributes
Use global constants appropriately:
// file: constant.dart
class Constant {
static const COLOR_TITLE = Color(0xFF202020);
static const COLOR_SUBTITLE = Color(0xFF88888A);
static const COLOR_MUTE = Color(0xccccccff);
static const COLOR_WARN = Color(0xFFF59A23);
static const COLOR_ERROR = Color(0xFFFA3651);
static const COLOR_PRIMARY = Color(0xFFA33028);
static const COLOR_LINK = Color(0xCC61ADF3);
static const MAIN_TITLE = TextStyle(fontSize: 16, color: COLOR_TITLE);
static const SUB_TITLE = TextStyle(fontSize: 12, color: COLOR_SUBTITLE);
static const LINK = TextStyle(fontSize: 13, color: COLOR_LINK);
}
Copy the code
Use:
import '.. /constant.dart'; . Container( margin: EdgeInsets.only(top:3),
child: Text(
mCneterItem[0].hotdiscuss,
style: Constant.LINK,
)
Copy the code
Method 3: Use SizedBox instead of Container’s Margin and Spacer instead of Flex
If we use Container only to use its margin property, we can use SizedBox and Spacer instead. Such as:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 5), Input( ... ) , SizedBox(height:5), Input( ... ) ,),,)Copy the code
Spacer simply wraps a Expanded SizedBox. It gives us flexibility to control Row/Column
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
color: Colors.blue,
margin: EdgeInsets.symmetric(horizontal: 5),
height: 50,
width: 50,
),
Spacer(flex: 2), // The elastic coefficient is 2
Container(
color: Colors.blue,
height: 50,
margin: EdgeInsets.symmetric(horizontal: 5),
width: 50,
),
Spacer(), // The elastic coefficient defaults to 1
Container(
color: Colors.blue,
margin: EdgeInsets.symmetric(horizontal: 5),
height: 50,
width: 50[], (), (Copy the code
4. Use Map instead of if else
Sometimes we use if else to return different component nesting, but only part of it is different. We can use Map or ternary syntax to return a variable, and we can use variables directly inside the component nesting. Example:
// Code before optimization:
if(level == 'level1') {
return Container(
width: (MediaQuery.of(context).size.width - 75) / 4,
height: (MediaQuery.of(context).size.width - 75) / 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
image: DecorationImage(
image: NetworkImage('https://hrlweibo-1259131655.cos.ap-beijing.myqcloud.com/pic1.jpg'),
fit: BoxFit.cover,
)),
)
} else {
return Container(
width: (MediaQuery.of(context).size.width - 75) / 4,
height: (MediaQuery.of(context).size.width - 75) / 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
image: DecorationImage(
image: NetworkImage('https://hrlweibo-1259131655.cos.ap-beijing.myqcloud.com/pic2.jpg'),
fit: BoxFit.cover,
)),
)
}
// Optimized code
urls = {
'level1': 'https://hrlweibo-1259131655.cos.ap-beijing.myqcloud.com/pic1.jpg'.'level2': 'https://hrlweibo-1259131655.cos.ap-beijing.myqcloud.com/pic1.jpg'
}
return Container(
width: (MediaQuery.of(context).size.width - 75) / 4,
height: (MediaQuery.of(context).size.width - 75) / 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
image: DecorationImage(
image: NetworkImage(urls[level]),
fit: BoxFit.cover,
)),
),
Copy the code
You might think you wouldn’t write code that crappy before optimization, but I see it all the time on Github, either because you’re lazy or because you don’t pay attention. At this point, review your code to see if it can be optimized.
Method 5: Use extension functions
This article is very good about extension functions: Flutter nested hell! This method is the ultimate solution to the nesting hell, but use it properly and don’t overuse it, otherwise it will affect your code reading. It is recommended to mainly use extension functions for style components such as color, size, paddig, visible, center, right, ClipOval, BorderRadius, etc. The author of the article also wrote an extension function library for us to use, which covers the commonly used extension functions, we can add their favorite extension functions on his basis.
Conclusion:
With the above 5 methods, I feel flutter smells good! Mom doesn’t have to worry about my nested hell problem anymore! Of course, each of these methods has its own scenarios and should be used in combination. Also, we need to learn how to refactor and remove duplicate code during development. Methods two and four actually remove duplicate code, thus avoiding nesting.