Skip to content

Commit aa51104

Browse files
Merge pull request #2 from vijayinyoutube/refactor
refactor
2 parents 314e174 + 77d748f commit aa51104

File tree

10 files changed

+241
-47
lines changed

10 files changed

+241
-47
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'package:flutter/material.dart';
2+
3+
import '../../Presentation/Components/snack_bar.dart';
4+
5+
enum ExceptionTypes {
6+
socketException,
7+
httpException,
8+
formatException,
9+
timeoutException
10+
}
11+
12+
class ExceptionHandlers {
13+
String typeOfException(ExceptionTypes exceptionTypes) {
14+
switch (exceptionTypes) {
15+
case ExceptionTypes.socketException:
16+
return 'No internet connection.';
17+
case ExceptionTypes.httpException:
18+
return 'HTTP error occured.';
19+
case ExceptionTypes.formatException:
20+
return 'Invalid data format.';
21+
case ExceptionTypes.timeoutException:
22+
return 'Request timeout.';
23+
}
24+
}
25+
}
26+
27+
class AppException implements Exception {
28+
final String? message;
29+
final String? prefix;
30+
final String? url;
31+
32+
AppException([this.message, this.prefix, this.url]);
33+
}
34+
35+
class BadRequestException extends AppException {
36+
BadRequestException([String? message, String? url])
37+
: super(message, 'Bad request', url);
38+
}
39+
40+
class FetchDataException extends AppException {
41+
FetchDataException([String? message, String? url])
42+
: super(message, 'Unable to process the request', url);
43+
}
44+
45+
class ApiNotRespondingException extends AppException {
46+
ApiNotRespondingException([String? message, String? url])
47+
: super(message, 'Api not responding', url);
48+
}
49+
50+
class UnAuthorizedException extends AppException {
51+
UnAuthorizedException([String? message, String? url])
52+
: super(message, 'Unauthorized request', url);
53+
}
54+
55+
class NotFoundException extends AppException {
56+
NotFoundException([String? message, String? url])
57+
: super(message, 'Page not found', url);
58+
}
59+

lib/Data/API/base_client.dart

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import 'dart:async';
2+
import 'dart:convert';
3+
import 'dart:io';
4+
5+
import '../../Business_Logic/Exceptions/exception_handlers.dart';
6+
import 'package:http/http.dart' as http;
7+
8+
class BaseClient {
9+
static const int timeOutDuration = 35;
10+
11+
//GET
12+
Future<dynamic> get(String url) async {
13+
var uri = Uri.parse(url);
14+
try {
15+
var response =
16+
await http.get(uri).timeout(const Duration(seconds: timeOutDuration));
17+
return _processResponse(response);
18+
} on SocketException {
19+
throw const SocketException('Socket exception');
20+
} on TimeoutException {
21+
throw ApiNotRespondingException('Server not responding.');
22+
} on FormatException {
23+
} on HttpException {
24+
} catch (e) {
25+
throw e.toString();
26+
}
27+
}
28+
29+
//POST
30+
Future<dynamic> post(String url, dynamic payloadObj) async {
31+
var uri = Uri.parse(url);
32+
var payload = jsonEncode(payloadObj);
33+
try {
34+
var response = await http
35+
.post(uri, body: payload)
36+
.timeout(const Duration(seconds: timeOutDuration));
37+
38+
return _processResponse(response);
39+
} on SocketException {
40+
} on TimeoutException {
41+
throw ApiNotRespondingException('Server not responding.');
42+
} on FormatException {
43+
} on HttpException {}
44+
}
45+
46+
//DELETE
47+
//OTHERS
48+
49+
//----------------------ERROR STATUS CODES----------------------
50+
51+
dynamic _processResponse(http.Response response) {
52+
switch (response.statusCode) {
53+
case 200:
54+
var responseJson = response.body;
55+
return responseJson;
56+
case 400: //Bad request
57+
throw BadRequestException(response.body);
58+
case 401: //Unauthorized
59+
throw UnAuthorizedException(response.body);
60+
case 403: //Forbidden
61+
throw UnAuthorizedException(response.body);
62+
case 404: //Resource Not Found
63+
throw NotFoundException(response.body);
64+
case 500: //Internal Server Error
65+
default:
66+
throw FetchDataException(
67+
'Something went wrong! ${response.statusCode}');
68+
}
69+
}
70+
}

lib/Data/Models/home_page_model.dart

+16-16
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
// ignore_for_file: public_member_api_docs, sort_constructors_first
22
import 'dart:convert';
33

4-
class DemoMode {
5-
final String userId;
6-
final String id;
4+
class DemoModel {
5+
final int userId;
6+
final int id;
77
final String title;
88
final bool completed;
99

10-
DemoMode(
10+
DemoModel(
1111
this.userId,
1212
this.id,
1313
this.title,
1414
this.completed,
1515
);
1616

17-
DemoMode copyWith({
18-
String? userId,
19-
String? id,
17+
DemoModel copyWith({
18+
int? userId,
19+
int? id,
2020
String? title,
2121
bool? completed,
2222
}) {
23-
return DemoMode(
23+
return DemoModel(
2424
userId ?? this.userId,
2525
id ?? this.id,
2626
title ?? this.title,
@@ -37,30 +37,30 @@ class DemoMode {
3737
};
3838
}
3939

40-
factory DemoMode.fromMap(Map<String, dynamic> map) {
41-
return DemoMode(
42-
map['userId'] as String,
43-
map['id'] as String,
40+
factory DemoModel.fromMap(Map<String, dynamic> map) {
41+
return DemoModel(
42+
map['userId'] as int,
43+
map['id'] as int,
4444
map['title'] as String,
4545
map['completed'] as bool,
4646
);
4747
}
4848

4949
String toJson() => json.encode(toMap());
5050

51-
factory DemoMode.fromJson(String source) =>
52-
DemoMode.fromMap(json.decode(source) as Map<String, dynamic>);
51+
factory DemoModel.fromJson(String source) =>
52+
DemoModel.fromMap(json.decode(source) as Map<String, dynamic>);
5353

5454
@override
5555
String toString() {
56-
return 'DemoMode(userId: $userId, id: $id, title: $title, completed: $completed)';
56+
return 'DemoModel(userId: $userId, id: $id, title: $title, completed: $completed)';
5757
}
5858

5959
@override
6060
bool operator ==(Object other) {
6161
if (identical(this, other)) return true;
6262

63-
return other is DemoMode &&
63+
return other is DemoModel &&
6464
other.userId == userId &&
6565
other.id == id &&
6666
other.title == title &&
+18-26
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,22 @@
1-
import 'package:api_exceptions_part2/Presentation/Screens/HomePage/UI/home_page.dart';
2-
import 'package:flutter/material.dart';
1+
import '../../Business_Logic/Exceptions/exception_handlers.dart';
2+
import '../API/base_client.dart';
3+
import '../Models/home_page_model.dart';
4+
import 'package:flutter_dotenv/flutter_dotenv.dart';
35

4-
class RouteGenerator {
5-
Route<dynamic> generateRoute(RouteSettings settings) {
6-
final args = settings.arguments;
7-
print(args.hashCode);
8-
switch (settings.name) {
9-
case '/':
10-
return MaterialPageRoute(
11-
builder: (_) => const MyHomePage(title: 'API & Exceptions'));
12-
13-
default:
14-
return _errorRoute();
15-
}
16-
}
6+
abstract class DemoRepository {
7+
Future<DemoModel> fetchData();
8+
}
179

18-
static Route<dynamic> _errorRoute() {
19-
return MaterialPageRoute(builder: (_) {
20-
return Scaffold(
21-
appBar: AppBar(
22-
title: const Text('Error'),
23-
),
24-
body: const Center(
25-
child: Text('ERROR'),
26-
),
27-
);
28-
});
10+
class DemoRepo extends DemoRepository {
11+
@override
12+
Future<DemoModel> fetchData() async {
13+
try{
14+
final response =
15+
await BaseClient().get('${(dotenv.env['API_BASE_URL'])}/todos/1');
16+
return DemoModel.fromJson(response);
17+
}
18+
catch(e){
19+
throw e.toString();
20+
}
2921
}
3022
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import 'package:flutter/material.dart';
2+
3+
ScaffoldFeatureController buildSnackBar(context, data) =>
4+
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(data)));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import '../../Presentation/Screens/HomePage/UI/home_page.dart';
2+
import 'package:flutter/material.dart';
3+
4+
class RouteGenerator {
5+
Route<dynamic> generateRoute(RouteSettings settings) {
6+
final args = settings.arguments;
7+
switch (settings.name) {
8+
case '/':
9+
return MaterialPageRoute(
10+
builder: (_) => const MyHomePage(title: 'API & Exceptions'));
11+
12+
default:
13+
return _errorRoute();
14+
}
15+
}
16+
17+
static Route<dynamic> _errorRoute() {
18+
return MaterialPageRoute(builder: (_) {
19+
return Scaffold(
20+
appBar: AppBar(
21+
title: const Text('Error'),
22+
),
23+
body: const Center(
24+
child: Text('ERROR'),
25+
),
26+
);
27+
});
28+
}
29+
}

lib/Presentation/Screens/HomePage/UI/home_page.dart

+16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:api_exceptions_part2/Data/Repository/home_page_repo.dart';
12
import 'package:flutter/material.dart';
23

34
class MyHomePage extends StatefulWidget {
@@ -16,6 +17,21 @@ class _MyHomePageState extends State<MyHomePage> {
1617
appBar: AppBar(
1718
title: Text(widget.title),
1819
),
20+
body: Center(
21+
child: ElevatedButton(
22+
onPressed: () => getData(),
23+
child: const Text('Fetch Data'),
24+
)),
1925
);
2026
}
27+
28+
Future<void> getData() async {
29+
print('getting data');
30+
try {
31+
var response = await DemoRepo().fetchData();
32+
print(response);
33+
} catch (e) {
34+
print(e.toString());
35+
}
36+
}
2137
}

lib/main.dart

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_dotenv/flutter_dotenv.dart';
23

3-
import 'Data/Repository/home_page_repo.dart';
4-
import 'Presentation/Screens/HomePage/UI/home_page.dart';
4+
import 'Presentation/Routes/generated_routes.dart';
55

6-
void main() {
6+
Future<void> main() async {
7+
await dotenv.load();
78
runApp(const MyApp());
89
}
910

@@ -13,6 +14,7 @@ class MyApp extends StatelessWidget {
1314
@override
1415
Widget build(BuildContext context) {
1516
return MaterialApp(
17+
debugShowCheckedModeBanner: false,
1618
title: 'Flutter API Exceptions',
1719
theme: ThemeData(
1820
primarySwatch: Colors.blue,

pubspec.lock

+21
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,20 @@ packages:
8181
description: flutter
8282
source: sdk
8383
version: "0.0.0"
84+
http:
85+
dependency: "direct main"
86+
description:
87+
name: http
88+
url: "https://pub.dartlang.org"
89+
source: hosted
90+
version: "0.13.4"
91+
http_parser:
92+
dependency: transitive
93+
description:
94+
name: http_parser
95+
url: "https://pub.dartlang.org"
96+
source: hosted
97+
version: "4.0.1"
8498
lints:
8599
dependency: transitive
86100
description:
@@ -163,6 +177,13 @@ packages:
163177
url: "https://pub.dartlang.org"
164178
source: hosted
165179
version: "0.4.9"
180+
typed_data:
181+
dependency: transitive
182+
description:
183+
name: typed_data
184+
url: "https://pub.dartlang.org"
185+
source: hosted
186+
version: "1.3.1"
166187
vector_math:
167188
dependency: transitive
168189
description:

pubspec.yaml

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies:
3535
# Use with the CupertinoIcons class for iOS style icons.
3636
cupertino_icons: ^1.0.2
3737
flutter_dotenv: ^5.0.2
38+
http: ^0.13.4
3839

3940
dev_dependencies:
4041
flutter_test:
@@ -59,8 +60,8 @@ flutter:
5960
uses-material-design: true
6061

6162
# To add assets to your application, add an assets section, like this:
62-
# assets:
63-
# - images/a_dot_burr.jpeg
63+
assets:
64+
- .env
6465
# - images/a_dot_ham.jpeg
6566

6667
# An image asset can refer to one or more resolution-specific "variants", see

0 commit comments

Comments
 (0)