Flutter Development Practices: Choosing Flutter, Provider MVVM, Performance Optimization, Layout Techniques, and Common Issues
This article explains why Ctrip's team adopted Flutter for cross‑platform mobile development, details the use of Provider for MVVM state management, presents performance tuning methods, layout tricks, and solutions to common Flutter pitfalls, offering a comprehensive guide for mobile engineers.
In the competitive mobile era, Ctrip's Flutter team chose Flutter for its cross‑platform capabilities and native‑like performance, especially for complex pages and long lists.
Flutter’s advantages include JIT‑based hot reload for rapid development and AOT‑compiled ARM binaries for high runtime efficiency.
The team adopts the Provider package to implement MVVM architecture, using ChangeNotifier, MultiProvider, and context‑based ViewModel retrieval to achieve clean state sharing across widgets.
/// Multiple NotifierProviders example
return MultiProvider(providers: [
ChangeNotifierProvider(create: (context) => dataViewModel(mCommonAdvancedFilterRoot, query)),
ChangeNotifierProvider(create: (context) => UserPreferentialViewModel(query)),
ChangeNotifierProvider(create: (context) => UserPromotionViewModel())
], child: ListResearchPageful(query));Performance optimization techniques covered include building in Profile mode, using the performance overlay and Dart DevTools, lazy loading ListView.builder, controlling setState frequency, caching widgets, and pre‑caching images.
// Lazy ListView.builder example
ListView.builder(
itemCount: mList.length,
itemBuilder: (BuildContext context, int index) {
return Text("Recommended using ListView.builder()");
}
);Layout tips such as using IntrinsicHeight for equal heights, preloading data and images, and handling dynamic sizing with Flexible, Expanded, and Stack are discussed.
// Image pre‑cache example
(hotelListViewModel.currentPageHotels ?? []).forEach((element) {
var logo = element?.logo ?? "";
if (StringUtil.isNotEmpty(logo)) {
precacheImage(NetworkImage(logo), context);
}
});Common Flutter pitfalls—incorrect setState after disposal, negative constraints from MediaQuery, improper Provider notifications, and Text.rich overflow—are analyzed with code examples and mitigation strategies.
// Safe setState with mounted check
if (mounted) {
setState(() {
_showCountDown = true;
});
} // Provider dispose pattern
class HotelViewModel extends ChangeNotifier {
bool _disposed = false;
@override
void dispose() {
_disposed = true;
super.dispose();
}
void hotelNotifyListeners() {
if (!_disposed) {
notifyListeners();
}
}
} // Text.rich overflow fix using Flexible
Row(
children: [
Flexible(
child: Text(itemRoomEntity.baseName ?? "", maxLines: 2, overflow: TextOverflow.ellipsis)
),
Container(child: Icon(HotelIcons.show_more))
]
);The article concludes that while Flutter outperforms React Native in complex UI scenarios, each cross‑platform solution has trade‑offs, and ongoing improvements in Flutter 2.0 make it a promising choice for future mobile development.
Ctrip Technology
Official Ctrip Technology account, sharing and discussing growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.