Benefits of using Consumer in Flutter
Detailed examples showcasing various use cases of Consumer
Conditional widget display
Form validation and submission
Enabling/disabling buttons
Navigation and routing
how Consumer helps in optimizing widget rebuilds
Techniques for building responsive and dynamic UIs
Using Consumer to handle loading states, errors, and data updates
Building dynamic and interactive forms
Validating and submitting forms with Consumer
Fetching and displaying data using Consumer
Real-time data updates and synchronization
Examples with APIs and databases
Using Consumer to manage state and data flow
Handling API calls, displaying articles, and managing states
Some common use of consumer widget
Displaying a Loading Indicator:
Use Consumer to show a loading spinner when data is being fetched.
Updating UI Based on Data:
Dynamically update other parts of your UI based on the data from the InfluencerViewModel.
Handling Errors:
Display error messages if data fetching fails.
ViewModel
Ensure your InfluencerViewModel has the necessary fields and methods.
class InfluencerViewModel extends ChangeNotifier {
bool isLoading = false;
List<SearchInfluencer> becomeinfluencers = [];
Map<String, dynamic> socialPrices = {};
Map<String, dynamic> socialurls = {};
String? digitalMarketer;
String? bio;
String? errorMessage;
Future<void> fetchInfluencersData(String? email) async {
isLoading = true;
errorMessage = null;
notifyListeners();
print("Fetching task data for email: $email");
try {
SearchInfluencer influencer = await api.influencerData(email);
becomeinfluencers = [influencer];
socialPrices = jsonDecode(becomeinfluencers.first.socialPrice ?? '{}');
socialurls = jsonDecode(becomeinfluencers.first.socialSite ?? '{}');
digitalMarketer = becomeinfluencers.first.digitalMarketer;
bio = becomeinfluencers.first.bio;
print(becomeinfluencers);
print(digitalMarketer);
print("Tasks fetched successfully");
} catch (e) {
errorMessage = "Error fetching tasks: $e";
print(errorMessage);
} finally {
isLoading = false;
notifyListeners();
}
}
}
TabScreen Widget
Use Consumer to handle different UI states such as loading, error, and displaying fetched data.
class TabScreen extends StatefulWidget {
@override
_TabScreenState createState() => _TabScreenState();
}
class _TabScreenState extends State<TabScreen> {
int _currentIndex = 0;
final List<String> _titles = [
'Add social site',
'Set Price',
'Describe',
];
final List<String> social_site = [
'facebook',
'twitter',
'youtube',
'wordpress',
'tumbler',
'instagram',
'quora',
'pinterest',
'reddit',
'telegram',
'linkedin',
];
List<List<String>> _fieldLabels = [
[
'Enter your facebook url',
'Enter your twitter url',
'Enter your youtube url',
'Enter your wordpress url',
'Enter your tumbler url',
'Enter your instagram url',
'Enter your quora url',
'Enter your pinterest url',
'Enter your reddit url',
'Enter your telegram url',
'Enter your linkedin url',
],
[
'Enter your facebook url',
'Enter your twitter url',
'Enter your youtube url',
'Enter your wordpress url',
'Enter your tumbler url',
'Enter your instagram url',
'Enter your quora url',
'Enter your pinterest url',
'Enter your reddit url',
'Enter your telegram url',
'Enter your linkedin url',
],
[
'Influencer As',
'Biography',
],
];
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => FormViewModel(InfluencerAPI())),
ChangeNotifierProvider(create: (_) => InfluencerViewModel(InfluencerAPI())),
],
child: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.blue,
centerTitle: true,
title: Text('Wizbrand', style: TextStyle(color: Colors.white)),
bottom: TabBar(
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
labelColor: Colors.white,
unselectedLabelColor: Colors.white70,
indicatorColor: Colors.white,
tabs: [
Tab(text: 'Add social site'),
Tab(text: 'Set Price'),
Tab(text: 'Describe'),
],
),
),
body: Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading) {
return Center(child: CircularProgressIndicator());
}
if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!));
}
// Update the field labels with the values from the view model
_fieldLabels[2] = [
viewModel.digitalMarketer ?? 'Influencer As',
viewModel.bio ?? 'Biography',
];
final List<Widget> _tabs = [
FormWidget(title: 'Add social site', fieldLabels: _fieldLabels[0], socialSite: social_site),
FormWidget(title: 'Set Price', fieldLabels: _fieldLabels[1], socialSite: social_site),
FormWidget(title: 'Describe', fieldLabels: _fieldLabels[2], socialSite: social_site),
];
return TabBarView(
children: _tabs,
);
},
),
),
),
);
}
}
Explanation
Loading Indicator
:
Inside the Consumer widget, check if viewModel.isLoading is true. If it is, show a CircularProgressIndicator.
Error Handling
:
If viewModel.errorMessage is not null, display the error message.
Updating UI Based on Data
:
If neither loading nor error states are active, update _fieldLabels with the values from the InfluencerViewModel and display the tabs.
By using the Consumer widget in these ways, you ensure that your UI reacts appropriately to changes in the data, whether it's displaying a loading indicator, handling errors, or updating the UI with the fetched data.
output
body: Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
final List<List<String>> _fieldLabels = [
viewModel.socialUrls,
viewModel.socialUrls,
[
viewModel.digitalMarketer ?? 'Influencer As',
viewModel.bio ?? 'Biography',
],
];
some additional uses of the Consumer widget in your Flutter application:
Conditional Widget Display:
Show or hide widgets based on the state of the data in your view model.
Form Validation and Submission:
Validate form fields and handle form submission using the view model state.
Enabling/Disabling Buttons:
Enable or disable buttons based on conditions in the view model (e.g., form completion, data loading).
Navigation and Routing:
Trigger navigation based on the state of the view model (e.g., redirecting after successful data fetch or form submission).
List Filtering and Sorting:
Display filtered or sorted lists based on user input or view model data.
Custom Animations:
Trigger animations based on changes in the view model state.
Data Refresh and Retry:
Provide a mechanism to retry data fetching if an error occurs, using a button or swipe-to-refresh functionality.
Theming and Styling:
Change the theme or style of widgets dynamically based on the view model state.
Here are some code snippets demonstrating these use cases:
Conditional Widget Display
Show a widget only if a condition is met in the view model.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
return viewModel.digitalMarketer != null
? Text("Digital Marketer: ${viewModel.digitalMarketer}")
: Container(); // Display nothing if digitalMarketer is null
},
);
Form Validation and Submission
Use the view model to validate form fields and handle form submission.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
return Column(
children: [
TextField(
onChanged: (value) {
viewModel.updateBio(value);
},
decoration: InputDecoration(
errorText: viewModel.isBioValid ? null : 'Bio is required',
),
),
ElevatedButton(
onPressed: viewModel.isFormValid ? () => viewModel.submitForm() : null,
child: Text('Submit'),
),
],
);
},
);
Enabling/Disabling Buttons
Enable or disable a button based on a condition in the view model.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
return ElevatedButton(
onPressed: viewModel.isLoading ? null : () => viewModel.fetchInfluencersData(email),
child: viewModel.isLoading ? CircularProgressIndicator() : Text('Fetch Data'),
);
},
);
Navigation and Routing
Navigate to a different screen based on a condition in the view model.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
if (viewModel.dataFetched) {
Future.microtask(() => Navigator.pushNamed(context, '/nextScreen'));
}
return Container(); // Placeholder while checking the condition
},
);
List Filtering and Sorting
Filter and display a list of items based on user input or view model data.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
final filteredList = viewModel.items.where((item) => item.contains(viewModel.filter)).toList();
return ListView.builder(
itemCount: filteredList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(filteredList[index]),
);
},
);
},
);
Custom Animations
Trigger animations based on changes in the view model state.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
return AnimatedOpacity(
opacity: viewModel.isDataVisible ? 1.0 : 0.0,
duration: Duration(seconds: 1),
child: Text('Data Loaded'),
);
},
);
Data Refresh and Retry
Provide a retry mechanism if data fetching fails.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
return viewModel.errorMessage != null
? Column(
children: [
Text(viewModel.errorMessage!),
ElevatedButton(
onPressed: () => viewModel.fetchInfluencersData(email),
child: Text('Retry'),
),
],
)
: Container(); // Display nothing if there's no error
},
);
Theming and Styling
Change the theme or style of widgets dynamically based on the view model state.
Consumer<InfluencerViewModel>(
builder: (context, viewModel, child) {
return Text(
'Themed Text',
style: TextStyle(
color: viewModel.isDarkTheme ? Colors.white : Colors.black,
),
);
},
);
These are just a few examples of how you can leverage the Consumer widget in your Flutter application to create a dynamic, responsive UI that reacts to changes in the state managed by your view model.
Top comments (0)