smart_fetch 1.0.7
smart_fetch: ^1.0.7 copied to clipboard
Beautiful full-screen error pages for server side errors and no internet connection state.
example/smart_fetch_example.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:smart_fetch/smart_fetch.dart';
// Example: Using SmartFetch.call() with SnackBar
// final result = await SmartFetch.call(
// () => http.get(Uri.parse('https://api.example.com/data')),
// context: context,
// errorSnackBar: const SnackBar(
// content: Text('Request failed. Please try again.'),
// backgroundColor: Colors.red,
// ),
// );
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SmartFetch Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: const LoginExamplePage(),
);
}
}
class LoginExamplePage extends StatefulWidget {
const LoginExamplePage({super.key});
@override
State<LoginExamplePage> createState() => _LoginExamplePageState();
}
class _LoginExamplePageState extends State<LoginExamplePage> {
final emailController = TextEditingController(text: 'test@example.com');
final passwordController = TextEditingController(text: 'password123');
bool shouldLogin = false;
int loginTrigger = 0;
@override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SmartFetch Login Example'),
backgroundColor: Colors.blue,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Testing SmartFetch.builder()',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 30),
TextField(
controller: emailController,
decoration: const InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: passwordController,
obscureText: true,
decoration: const InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 30),
if (!shouldLogin)
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: () {
setState(() {
shouldLogin = true;
loginTrigger++;
});
},
style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
child: const Text(
'Login with SmartFetch',
style: TextStyle(fontSize: 16, color: Colors.white),
),
),
)
else
SizedBox(
height: 200,
child: SmartFetch.builder(
key: ValueKey('login_fetch_$loginTrigger'),
future: () {
final body = {
"email": emailController.text,
"password": passwordController.text,
};
final headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
return http.post(
Uri.parse('https://api.example.com/login'),
headers: headers,
body: jsonEncode(body),
);
},
loadingWidget: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(color: Colors.blue),
SizedBox(height: 16),
Text('Logging in...'),
],
),
),
onSuccess: (context, response) {
if (response.statusCode == 200) {
try {
return const Center(
child: Text('Login Successful!'),
); // TODO: Add your success widget here
} catch (e) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
shouldLogin = false;
});
}
});
return Center(
child: Card(
color: Colors.red.shade50,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text('Error: $e'),
),
),
);
}
} else {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
shouldLogin = false;
});
}
});
return Center(
child: Card(
color: Colors.red.shade50,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.error,
color: Colors.red,
size: 48,
),
const SizedBox(height: 8),
Text(
'Login Failed!',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.red.shade700,
),
),
const SizedBox(height: 8),
Text(
'Status: ${response.statusCode}',
style: const TextStyle(fontSize: 14),
),
],
),
),
),
);
}
},
timeout: const Duration(seconds: 10),
// Optional: Show SnackBar when error occurs
// errorSnackBar: const SnackBar(
// content: Text('Login failed. Please try again.'),
// backgroundColor: Colors.orange,
// duration: Duration(seconds: 4),
// ),
onError: (context, error) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final errorScreen =
error.isTimeout
? const TimeoutScreen()
: error.isNoInternet
? const NoInternetScreen()
: const ServerErrorScreen();
await Navigator.push(
context,
MaterialPageRoute(builder: (_) => errorScreen),
);
if (mounted) {
setState(() {
shouldLogin = false;
});
}
});
return const SizedBox.shrink();
},
),
),
],
),
),
);
}
}