Flutter实现从REST API取状态并自动刷新的Widget基础指南
Hey there! Let's build this Flutter widget that covers all your requirements—loading state, async API fetch, state updates on success, and auto-refresh. I'll walk you through each part with copy-pasteable code examples you can tweak to fit your needs.
1. Start with a Stateful Widget
Since we need to manage changing states (loading, fetched data, timer), a StatefulWidget is a must. Here's the base structure:
class AutoRefreshingContent extends StatefulWidget { const AutoRefreshingContent({super.key}); @override State<AutoRefreshingContent> createState() => _AutoRefreshingContentState(); } class _AutoRefreshingContentState extends State<AutoRefreshingContent> { bool _isLoading = true; String? _fetchedContent; Timer? _refreshTimer; final Duration _refreshDelay = const Duration(seconds: 10); // Adjust refresh rate here @override void initState() { super.initState(); _loadInitialData(); // Fetch data when widget first loads _setupAutoRefresh(); // Start the auto-refresh timer } @override void dispose() { _refreshTimer?.cancel(); // Clean up timer to avoid memory leaks super.dispose(); } // We'll add our core logic methods here next @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Auto-Refreshing Content")), body: const Center(child: Text("Loading...")), // Temp placeholder ); } }
2. Add Async API Fetch Logic
First, add the http package to your pubspec.yaml (run flutter pub get after saving):
dependencies: flutter: sdk: flutter http: ^1.1.0
Now implement the _loadInitialData method to handle API calls with error handling:
import 'package:http/http.dart' as http; import 'dart:convert'; Future<void> _loadInitialData() async { setState(() => _isLoading = true); // Show loading state before fetching try { final response = await http.get(Uri.parse("https://your-api-url.com/data")); // Replace with your API endpoint if (response.statusCode == 200) { // Parse the response—adjust this to match your API's JSON structure final apiResponse = jsonDecode(response.body); setState(() { _fetchedContent = apiResponse["content"]; // Example: using a "content" field from API _isLoading = false; }); } else { throw Exception("API returned status code: ${response.statusCode}"); } } catch (e) { setState(() { _isLoading = false; _fetchedContent = null; // Flag error state debugPrint("Error fetching data: $e"); }); } }
3. Implement Auto-Refresh
Add the _setupAutoRefresh method to trigger data fetching at your desired interval:
void _setupAutoRefresh() { _refreshTimer = Timer.periodic(_refreshDelay, (timer) { _loadInitialData(); // Refresh data every time the timer ticks }); }
4. Build the Responsive UI
Update the build method to show different UI based on current state (loading, success, error):
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Auto-Refreshing Content")), body: Padding( padding: const EdgeInsets.all(16.0), child: Center( child: _isLoading ? const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text("Loading content..."), ], ) : _fetchedContent != null ? Text( _fetchedContent!, style: const TextStyle(fontSize: 18), textAlign: TextAlign.center, ) : const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.error_outline, color: Colors.red, size: 48), SizedBox(height: 16), Text("Oops! Failed to load content. Retrying automatically..."), ], ), ), ), ); }
- Memory Safety: Always cancel the timer in
dispose()to prevent memory leaks. - API Flexibility: Modify the JSON parsing logic to match your API's response format (e.g., if it returns a list instead of a single string).
- Refresh Rate: Adjust
_refreshDelayto make content refresh faster or slower.
内容的提问来源于stack exchange,提问作者dakamojo

