Skip to main content

24 posts tagged with "Flutter"

View All Tags

Animation và Custom Painting Trong Flutter

· 3 min read

Animation Cơ bản​

AnimationController​

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
late AnimationController _controller;

@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}
}

Tween Animation​

final animation = Tween<double>(
begin: 0,
end: 300,
).animate(_controller);

Các Loại Animation​

Implicit Animations​

AnimatedContainer(
duration: Duration(milliseconds: 500),
width: _isExpanded ? 300.0 : 100.0,
height: _isExpanded ? 300.0 : 100.0,
color: _isExpanded ? Colors.blue : Colors.red,
curve: Curves.fastOutSlowIn,
)

Hero Animation​

Hero(
tag: 'imageHero',
child: Image.network('url_to_image'),
)

Staggered Animations​

class StaggeredAnimation extends StatelessWidget {
final Animation<double> controller;
late final Animation<double> opacity;
late final Animation<double> width;
late final Animation<double> height;

StaggeredAnimation({required this.controller}) {
opacity = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.0, 0.100, curve: Curves.ease),
),
);
}
}

Custom Painting​

CustomPaint và CustomPainter​

class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..strokeWidth = 4
..style = PaintingStyle.stroke;

canvas.drawCircle(
Offset(size.width / 2, size.height / 2),
100,
paint,
);
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}

Vẽ Đường Cong​

void drawCurve(Canvas canvas, Size size) {
var path = Path();
path.moveTo(0, size.height / 2);
path.quadraticBezierTo(
size.width / 2,
0,
size.width,
size.height / 2,
);
canvas.drawPath(path, paint);
}

Hiệu Ứng Nâng Cao​

Particle System​

class Particle {
Offset position;
double speed;
double theta;
Color color;

void update() {
final dx = speed * cos(theta);
final dy = speed * sin(theta);
position += Offset(dx, dy);
}

void draw(Canvas canvas) {
final paint = Paint()..color = color;
canvas.drawCircle(position, 2, paint);
}
}

Shader Effects​

final shader = LinearGradient(
colors: [Colors.blue, Colors.red],
).createShader(Rect.fromLTWH(0, 0, size.width, size.height));

final paint = Paint()..shader = shader;

Performance Optimization​

Repaint Boundary​

RepaintBoundary(
child: CustomPaint(
painter: MyPainter(),
),
)

Caching Complex Paintings​

class CachedPainter extends CustomPainter {
ui.Picture? _cachedPicture;

void _createCachedPicture(Size size) {
final recorder = ui.PictureRecorder();
final canvas = Canvas(recorder);
// Draw complex stuff
_cachedPicture = recorder.endRecording();
}
}

Best Practices​

Animation​

  • Sử dụng vsync để tránh memory leak
  • Dispose AnimationController khi widget bị dispose
  • Sử dụng Implicit Animation khi có thể
  • Tránh animation quá phức tạp trên mobile

Custom Painting​

  • Sử dụng RepaintBoundary để tối ưu hiệu năng
  • Cache các painting phức tạp
  • Tránh vẽ lại không cần thiết

Tài Liệu Tham Khảo​

Các Design Pattern Phổ Biến Trong Flutter

· 3 min read

1. MVC (Model-View-Controller)​

1.1. Cấu Trúc​

  • Model: Quản lý dữ liệu và logic
  • View: Hiển thị UI
  • Controller: Xử lý tương tác người dùng

1.2. Ví Dụ​

// Model
class User {
final String name;
final String email;
User(this.name, this.email);
}

// Controller
class UserController {
void updateUser(User user) {
// Logic xử lý
}
}

// View
class UserView extends StatelessWidget {
// UI components
}

2. MVVM (Model-View-ViewModel)​

2.1. Thành Phần​

  • Model: Data và business logic
  • View: UI và user interactions
  • ViewModel: Kết nối Model và View

2.2. Implemention với Provider​

class UserViewModel extends ChangeNotifier {
User _user;
User get user => _user;

void updateUser(User newUser) {
_user = newUser;
notifyListeners();
}
}

3. Repository Pattern​

3.1. Cấu Trúc​

  • Repository Interface
  • Remote Data Source
  • Local Data Source
  • Repository Implementation

3.2. Code Mẫu​

abstract class UserRepository {
Future<User> getUser(int id);
Future<void> saveUser(User user);
}

class UserRepositoryImpl implements UserRepository {
final RemoteDataSource remote;
final LocalDataSource local;

UserRepositoryImpl(this.remote, this.local);

@override
Future<User> getUser(int id) async {
// Implementation
}
}

4. Singleton Pattern​

4.1. Đặc Điểm​

  • Một instance duy nhất
  • Global access point
  • Lazy initialization

4.2. Ví Dụ​

class ApiClient {
static final ApiClient _instance = ApiClient._internal();

factory ApiClient() {
return _instance;
}

ApiClient._internal();
}

5. Factory Pattern​

5.1. Ứng Dụng​

  • Tạo objects động
  • Encapsulation logic khởi tạo
  • Tái sử dụng code

5.2. Implementation​

abstract class Button {
void render();
}

class ButtonFactory {
static Button createButton(String type) {
switch (type) {
case 'material':
return MaterialButton();
case 'cupertino':
return CupertinoButton();
default:
throw Exception('Unknown button type');
}
}
}

6. Observer Pattern​

6.1. Sử Dụng​

  • State management
  • Event handling
  • Real-time updates

6.2. Ví Dụ Với Stream​

class DataStream {
final _controller = StreamController<Data>();

Stream<Data> get stream => _controller.stream;

void updateData(Data data) {
_controller.sink.add(data);
}
}

7. Builder Pattern​

7.1. Ưu Điểm​

  • Xây dựng object phức tạp
  • Step-by-step construction
  • Flexible configuration

7.2. Code Example​

class UserBuilder {
String? name;
String? email;

UserBuilder setName(String name) {
this.name = name;
return this;
}

User build() {
return User(name!, email!);
}
}

8. Best Practices​

8.1. Khi Nào Sử Dụng​

  • Dự án lớn, phức tạp
  • Cần tái sử dụng code
  • Maintain dài hạn
  • Team development

8.2. Lưu Ý​

  • Không over-engineering
  • Chọn pattern phù hợp
  • Documentation đầy đủ
  • Unit testing

9. Anti-patterns Cần Tránh​

  • Massive View Controllers
  • God Objects
  • Tight Coupling
  • Duplicate Code

10. Tools và Resources​

  • Analysis tools
  • Linter rules
  • Design pattern libraries
  • Code generators

Cơ Hội Nghề Nghiệp Với Flutter

· 3 min read

1. Tổng Quan Thị Trường​

  • Flutter đang phát triển nhanh chóng trong cộng đồng phát triển di động
  • Được Google hỗ trợ mạnh mẽ
  • Nhu cầu tuyển dụng lập trình viên Flutter tăng cao
  • Mức lương cạnh tranh trong ngành công nghệ

2. Vị Trí Công Việc Phổ Biến​

2.1. Flutter Developer​

  • Phát triển ứng dụng di động đa nền tảng
  • Làm việc với REST APIs
  • Tối ưu hiệu suất ứng dụng
  • Mức lương: 15-35 triệu VNĐ (Junior), 35-70 triệu VNĐ (Senior)

2.2. Mobile Technical Lead​

  • Quản lý team phát triển
  • Thiết kế kiến trúc ứng dụng
  • Code review và mentoring
  • Mức lương: 70-120 triệu VNĐ

2.3. Flutter Consultant​

  • Tư vấn giải pháp kỹ thuật
  • Đào tạo và hướng dẫn
  • Tối ưu quy trình phát triển
  • Mức lương: Theo dự án hoặc giờ tư vấn

3. Ngành Công Nghiệp Sử Dụng Flutter​

3.1. Công Ty Phần Mềm​

  • Startup công nghệ
  • Công ty outsourcing
  • Các tập đoàn lớn

3.2. Các Lĩnh Vực​

  • Fintech
  • E-commerce
  • Healthcare
  • Education
  • Entertainment
  • Social Media

4. Kỹ Năng Cần Thiết​

4.1. Kỹ Năng Kỹ Thuật​

  • Dart programming
  • Flutter framework
  • State management
  • API integration
  • Database management
  • Version control (Git)
  • Testing và debugging

4.2. Kỹ Năng Mềm​

  • Giao tiếp hiệu quả
  • Làm việc nhóm
  • Quản lý thời gian
  • Giải quyết vấn đề
  • Tư duy logic

5. Con Đường Phát Triển Sự Nghiệp​

5.1. Junior Developer (0-2 năm)​

  • Học Flutter cơ bản
  • Làm việc dưới sự hướng dẫn
  • Phát triển các tính năng đơn giản

5.2. Mid-level Developer (2-4 năm)​

  • Xử lý các task phức tạp
  • Tối ưu hiệu suất ứng dụng
  • Mentor junior developers

5.3. Senior Developer (4+ năm)​

  • Thiết kế kiến trúc hệ thống
  • Lead các dự án lớn
  • Đưa ra quyết định kỹ thuật

6. Cơ Hội Freelance​

  • Upwork
  • Freelancer
  • Fiverr
  • Các dự án độc lập
  • Consulting

7. Xu Hướng Tương Lai​

  • Cross-platform development tiếp tục phát triển
  • Flutter Web và Desktop apps
  • Integration với AI/ML
  • IoT và Flutter
  • Flutter trong AR/VR

8. Lời Khuyên Cho Người Mới Bắt Đầu​

  • Xây dựng portfolio mạnh
  • Tham gia cộng đồng Flutter
  • Đóng góp open source
  • Thường xuyên cập nhật kiến thức
  • Networking với các developer khác

9. Nguồn Học Tập​

  • Flutter.dev (Documentation chính thức)
  • Udemy, Coursera
  • Flutter YouTube channels
  • Stack Overflow
  • GitHub repositories

Flutter với Firebase

· 3 min read

Cài đặt và Cấu hình​

Thêm Dependencies​

dependencies:
firebase_core: ^2.24.2
firebase_auth: ^4.15.3
cloud_firestore: ^4.13.6
firebase_storage: ^11.5.6

Khởi tạo Firebase​

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}

Authentication​

Đăng ký người dùng​

Future<UserCredential> signUpWithEmail(String email, String password) async {
try {
return await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
throw _handleAuthError(e);
}
}

Đăng nhập​

Future<UserCredential> signInWithEmail(String email, String password) async {
try {
return await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
throw _handleAuthError(e);
}
}

Cloud Firestore​

CRUD Operations​

// Thêm dữ liệu
Future<void> addUser(String userId, Map<String, dynamic> userData) async {
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.set(userData);
}

// Đọc dữ liệu
Future<DocumentSnapshot> getUser(String userId) async {
return await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.get();
}

// Cập nhật dữ liệu
Future<void> updateUser(String userId, Map<String, dynamic> newData) async {
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.update(newData);
}

// Xóa dữ liệu
Future<void> deleteUser(String userId) async {
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.delete();
}

Realtime Updates​

Stream<QuerySnapshot> getUsersStream() {
return FirebaseFirestore.instance
.collection('users')
.snapshots();
}

// Sử dụng trong Widget
StreamBuilder<QuerySnapshot>(
stream: getUsersStream(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Có lỗi xảy ra');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
return ListView(
children: snapshot.data!.docs.map((doc) {
return ListTile(
title: Text(doc['name']),
);
}).toList(),
);
},
)

Cloud Storage​

Upload Files​

Future<String> uploadFile(File file, String path) async {
try {
final ref = FirebaseStorage.instance.ref().child(path);
final uploadTask = ref.putFile(file);
final snapshot = await uploadTask.whenComplete(() {});
return await snapshot.ref.getDownloadURL();
} catch (e) {
throw Exception('Lỗi khi upload file: $e');
}
}

Download Files​

Future<void> downloadFile(String url, String localPath) async {
try {
final ref = FirebaseStorage.instance.refFromURL(url);
final file = File(localPath);
await ref.writeToFile(file);
} catch (e) {
throw Exception('Lỗi khi download file: $e');
}
}

Security Rules​

Firestore Rules​

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == userId;
}
}
}

Storage Rules​

rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read: if request.auth != null;
allow write: if request.auth != null;
}
}
}

Best Practices​

Authentication​

  • Luôn xử lý lỗi authentication
  • Sử dụng các phương thức bảo mật như email verification
  • Implement proper session management

Database​

  • Cấu trúc dữ liệu phù hợp
  • Sử dụng indexes cho queries phức tạp
  • Implement caching cho offline support

Storage​

  • Validate file size và type trước khi upload
  • Implement progress monitoring cho large files
  • Sử dụng compression khi cần thiết

Tài Liệu Tham Khảo​

Kiến Trúc Của Flutter như thế nào

· 2 min read

1. Tổng Quan Kiến Trúc Flutter​

Flutter được xây dựng với kiến trúc layer, trong đó mỗi layer được xây dựng dựa trên các layer bên dưới. Kiến trúc này bao gồm:

  • Flutter Engine
  • Foundation Library
  • Design-specific Widgets
  • Apps and Features

2. Flutter Engine​

Flutter Engine là core của framework, được viết bằng C++, cung cấp các chức năng low-level như:

  • Skia Graphics Engine
  • Text layout
  • File/Network I/O
  • Plugin architecture
  • Dart runtime

3. Foundation Library​

Foundation Library cung cấp các lớp và hàm cơ bản được sử dụng để xây dựng ứng dụng Flutter, bao gồm:

  • Các animation primitives
  • Gesture recognition
  • Painting primitives
  • Widget testing

4. Rendering Layer​

Layer này chịu trách nhiệm cho:

  • Layout system
  • Compositing
  • Paint operations

5. Widget Layer​

Flutter sử dụng widget như building blocks để xây dựng UI. Có hai loại widget chính:

  • StatelessWidget: Widget không có state
  • StatefulWidget: Widget có thể thay đổi state

6. State Management​

Flutter cung cấp nhiều giải pháp quản lý state:

// Provider Example
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => MyState(),
child: MaterialApp(
home: MyHomePage(),
),
);
}
}

7. Platform Channels​

Flutter sử dụng Platform Channels để giao tiếp với native code:

static const platform = MethodChannel('samples.flutter.dev/battery');

// Gọi native code
final int result = await platform.invokeMethod('getBatteryLevel');

8. Cấu Trúc Thư Mục Khuyến Nghị​

lib/
|- api/
|- models/
|- providers/
|- screens/
|- widgets/
|- utils/
|- main.dart

9. Performance Considerations​

Một số điểm cần lưu ý về hiệu năng:

  • Sử dụng const constructors khi có thể
  • Tránh rebuild không cần thiết
  • Tối ưu hóa images và assets
  • Sử dụng memory profiler để phát hiện memory leaks

10. Tài Liệu Tham Khảo​

Lộ Trình Tự Học Flutter Cho Người Mới Bắt Đầu

· 2 min read

1. Nền Tảng Cơ Bản (2-4 tuần)​

1.1. Ngôn Ngữ Dart​

  • Cú pháp cơ bản
  • Biến và kiểu dữ liệu
  • Hàm và phương thức
  • OOP trong Dart
  • Async programming

1.2. Công Cụ Phát Triển​

  • Cài đặt Flutter SDK
  • Android Studio/VS Code
  • Flutter DevTools
  • Git cơ bản

2. Flutter Cơ Bản (4-6 tuần)​

2.1. Widget Cơ Bản​

  • StatelessWidget
  • StatefulWidget
  • Material Design
  • Cupertino Design

2.2. Layout và UI​

  • Container và Box
  • Row và Column
  • Stack và Positioned
  • ListView và GridView
  • Custom Widgets

3. Flutter Nâng Cao (6-8 tuần)​

3.1. State Management​

  • setState
  • Provider
  • Bloc/Cubit
  • GetX
  • Riverpod

3.2. Navigation và Routing​

  • Navigator 1.0
  • Navigator 2.0
  • Deep linking
  • Route management

4. Tương Tác Backend (4-6 tuần)​

4.1. Network và API​

  • HTTP requests
  • RESTful APIs
  • JSON parsing
  • Authentication
  • WebSocket

4.2. Local Storage​

  • SharedPreferences
  • SQLite
  • Hive
  • File handling

5. Testing và Performance (3-4 tuần)​

5.1. Testing​

  • Unit testing
  • Widget testing
  • Integration testing
  • Test coverage

5.2. Performance​

  • Memory management
  • Frame rate optimization
  • App size reduction
  • Loading optimization

6. Các Project Thực Tế​

6.1. Project Cơ Bản​

  • Todo App
  • Weather App
  • Calculator
  • Note Taking App

6.2. Project Nâng Cao​

  • Social Media App
  • E-commerce App
  • Chat Application
  • Music Player

7. Tài Nguyên Học Tập​

7.1. Tài Liệu Chính Thức​

  • Flutter Documentation
  • Dart Documentation
  • Flutter YouTube Channel
  • Flutter Medium Blog

7.2. Khóa Học Online​

  • Flutter Bootcamp
  • Udemy Courses
  • Coursera
  • YouTube Tutorials

8. Thời Gian Dự Kiến​

  • Học part-time: 6-8 tháng
  • Học full-time: 3-4 tháng
  • Thực hành projects: 2-3 tháng

9. Tips Học Hiệu Quả​

  • Code mỗi ngày
  • Tham gia cộng đồng Flutter
  • Làm nhiều project thực tế
  • Đọc source code mẫu
  • Theo dõi Flutter trends

10. Tiếp Theo Sau Khi Hoàn Thành​

  • Tìm việc làm Flutter
  • Đóng góp open source
  • Xây dựng portfolio
  • Tiếp tục học các công nghệ mới
  • Chia sẻ kiến thức với cộng đồng

State Management Nâng Cao Trong Flutter

· 3 min read

Provider​

Provider là giải pháp quản lý state đơn giản và mạnh mẽ được Flutter team khuyên dùng.

Cài đặt Provider​

dependencies:
provider: ^6.0.0

Ví dụ Cơ bản với Provider​

// Model
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;

void increment() {
_count++;
notifyListeners();
}
}

// Widget sử dụng Provider
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => Counter(),
child: Consumer<Counter>(
builder: (context, counter, child) => Text('${counter.count}'),
),
);
}
}

Bloc (Business Logic Component)​

Bloc là pattern giúp tách biệt business logic khỏi presentation layer.

Cài đặt Bloc​

dependencies:
flutter_bloc: ^8.0.0

Ví dụ với Bloc​

// Events
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}

// State
class CounterState {
final int count;
CounterState(this.count);
}

// Bloc
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterState(0)) {
on<IncrementEvent>((event, emit) {
emit(CounterState(state.count + 1));
});
}
}

GetX​

GetX là giải pháp all-in-one cho state management, routing và dependency injection.

Cài đặt GetX​

dependencies:
get: ^4.6.0

Ví dụ với GetX​

// Controller
class CounterController extends GetxController {
var count = 0.obs;

void increment() => count++;
}

// Widget
class CounterWidget extends StatelessWidget {
final controller = Get.put(CounterController());

@override
Widget build(BuildContext context) {
return Obx(() => Text('${controller.count}'));
}
}

Riverpod​

Riverpod là phiên bản cải tiến của Provider, khắc phục một số hạn chế.

Cài đặt Riverpod​

dependencies:
flutter_riverpod: ^2.0.0

Ví dụ với Riverpod​

// Provider definition
final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter());

class Counter extends StateNotifier<int> {
Counter() : super(0);
void increment() => state++;
}

// Widget
class CounterWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text('$count');
}
}

So Sánh Các Giải Pháp​

Provider​

  • Ưu điểm: Đơn giản, dễ học, được Flutter team khuyên dùng
  • Nhược điểm: Có thể phức tạp khi ứng dụng lớn

Bloc​

  • Ưu điểm: Mạnh mẽ, có thể mở rộng, dễ test
  • Nhược điểm: Có learning curve cao, nhiều boilerplate code

GetX​

  • Ưu điểm: All-in-one solution, ít code
  • Nhược điểm: Có thể làm code khó maintain nếu không cẩn thận

Riverpod​

  • Ưu điểm: Type-safe, compile-time safety
  • Nhược điểm: Khái niệm mới cần thời gian làm quen

Khi Nào Sử Dụng Gì?​

  • Provider: Cho dự án nhỏ và vừa, team mới học Flutter
  • Bloc: Cho dự án lớn, cần tách biệt business logic rõ ràng
  • GetX: Cho dự án cần phát triển nhanh, ít người
  • Riverpod: Cho dự án cần type-safety cao, muốn tránh runtime errors

Tài Liệu Tham Khảo​

Testing Trong Flutter

· 2 min read

Giới Thiệu​

Testing là một phần quan trọng trong quá trình phát triển ứng dụng Flutter. Flutter hỗ trợ ba loại testing chính:

  • Unit Testing
  • Widget Testing
  • Integration Testing

Unit Testing​

Cài đặt Dependencies​

dev_dependencies:
test: ^1.24.0
mockito: ^5.4.0
build_runner: ^2.4.0

Ví dụ Unit Test​

// Class cần test
class Calculator {
int add(int a, int b) => a + b;
}

// Test file
import 'package:test/test.dart';

void main() {
group('Calculator', () {
late Calculator calculator;

setUp(() {
calculator = Calculator();
});

test('add should return correct sum', () {
expect(calculator.add(2, 3), equals(5));
});
});
}

Widget Testing​

Cài đặt​

dev_dependencies:
flutter_test:
sdk: flutter

Ví dụ Widget Test​

testWidgets('Counter increments smoke test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);

await tester.tap(find.byIcon(Icons.add));
await tester.pump();

expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});

Integration Testing​

Cài đặt​

dev_dependencies:
integration_test:
sdk: flutter

Ví dụ Integration Test​

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

testWidgets('Complete flow test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());

// Login flow
await tester.enterText(
find.byKey(Key('username')),
'testuser'
);
await tester.enterText(
find.byKey(Key('password')),
'password123'
);
await tester.tap(find.byType(ElevatedButton));
await tester.pumpAndSettle();

// Verify home screen
expect(find.text('Welcome'), findsOneWidget);
});
}

Mocking trong Flutter​

Sử dụng Mockito​

// Tạo mock class
@GenerateMocks([HttpClient])
void main() {
late MockHttpClient mockHttpClient;

setUp(() {
mockHttpClient = MockHttpClient();
});

test('fetchData returns data on success', () async {
when(mockHttpClient.get(any))
.thenAnswer((_) async => Response('{"data": "test"}', 200));

final result = await DataService(mockHttpClient).fetchData();
expect(result, equals('test'));
});
}

Best Practices​

Unit Testing​

  • Test một function/method độc lập
  • Tập trung vào business logic
  • Sử dụng mocking cho external dependencies

Widget Testing​

  • Test UI components
  • Verify widget rendering
  • Test user interactions

Integration Testing​

  • Test complete user flows
  • Verify app behavior end-to-end
  • Test real device interactions

Continuous Integration​

Cấu hình GitHub Actions​

name: Flutter CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: subosito/flutter-action@v2
- run: flutter test

Test Coverage​

Generating Coverage Reports​

# Run tests with coverage
flutter test --coverage

# Generate HTML report
genhtml coverage/lcov.info -o coverage/html

Tài Liệu Tham Khảo​

Tối Ưu Hiệu Năng Trong Flutter

· 3 min read

1. Phân Tích Hiệu Năng​

1.1. Công Cụ Đo Lường​

  • Flutter DevTools
  • Performance Overlay
  • Timeline Events
  • Memory Profiler

1.2. Các Chỉ Số Quan Trọng​

  • Frame Rate (FPS)
  • Memory Usage
  • App Size
  • Start-up Time

2. Tối Ưu Widget Tree​

2.1. const Constructor​

const MyWidget(
key: Key('my_widget'),
child: Text('Hello'),
)

2.2. Widget Rebuilding​

  • Sử dụng setState() hợp lý
  • Tách nhỏ widget
  • Dùng const widgets
  • Implement shouldRebuild

3. Quản Lý Bộ Nhớ​

3.1. Image Optimization​

  • Nén ảnh
  • Lazy loading
  • Caching
  • Proper image formats

3.2. Memory Leaks​

  • Dispose controllers
  • Cancel subscriptions
  • Clear caches
  • Release resources

4. Tối Ưu Build​

4.1. Code Organization​

  • Tách code thành packages
  • Lazy loading features
  • Code splitting
  • Tree shaking

4.2. Asset Management​

  • Compress assets
  • Remove unused resources
  • Optimize font loading
  • SVG thay vì PNG

5. Network Optimization​

5.1. API Calls​

  • Caching responses
  • Batch requests
  • Compression
  • Cancel unused requests

5.2. Background Processing​

  • Isolates
  • Compute functions
  • Background tasks
  • WorkManager

6. Animation Performance​

6.1. Efficient Animations​

AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Transform.translate(
offset: Offset(0, animation.value),
child: child,
);
},
child: const MyWidget(), // Cached
)

6.2. Best Practices​

  • Use RepaintBoundary
  • Avoid excessive animations
  • Hardware acceleration
  • Frame pacing

7. Database Optimization​

7.1. Local Storage​

  • Indexed queries
  • Batch operations
  • Proper schema design
  • Regular cleanup

7.2. Caching Strategy​

  • Memory cache
  • Disk cache
  • Network cache
  • Cache invalidation

8. Code Level Optimization​

8.1. Dart Code​

  • Async/await proper usage
  • Proper collection types
  • Constant values
  • Code minification

8.2. Platform Channels​

  • Minimize platform calls
  • Batch operations
  • Proper error handling
  • Background processing

9. Debug và Profile Mode​

9.1. Profile Mode​

  • Release mode testing
  • Performance metrics
  • Memory leaks
  • CPU usage

9.2. Debug Tools​

  • Flutter Inspector
  • Performance overlay
  • Debug flags
  • Logging

10. Kiểm Tra Hiệu Năng​

10.1. Automation​

  • Performance tests
  • Benchmark tests
  • CI/CD integration
  • Monitoring tools

10.2. Metrics​

  • Frame build time
  • Memory footprint
  • Network latency
  • App size metrics

Tự Học Flutter | Kết Hợp Flutter Với Backend API

· 2 min read

1. Cài Đặt Dependencies​

dependencies:
http: ^1.1.0
dio: ^5.4.0

2. Thiết Lập HTTP Client​

  • Sử dụng http package hoặc dio để thực hiện các request API
  • Cấu hình:
    • Base URL
    • Headers (Authentication, Content-Type)
    • Timeout
    • Interceptors

3. Tạo Model Classes​

class User {
final int id;
final String name;
final String email;

User({
required this.id,
required this.name,
required this.email,
});

factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
}

4. Xây Dựng API Service​

class ApiService {
final client = http.Client();
final baseUrl = 'https://api.example.com';

Future<List<User>> getUsers() async {
try {
final response = await client.get(
Uri.parse('$baseUrl/users'),
headers: {'Authorization': 'Bearer token'},
);

if (response.statusCode == 200) {
final List<dynamic> data = json.decode(response.body);
return data.map((json) => User.fromJson(json)).toList();
} else {
throw Exception('Lỗi lấy dữ liệu: ${response.statusCode}');
}
} catch (e) {
throw Exception('Lỗi kết nối: $e');
}
}
}

5. State Management​

class UserProvider extends ChangeNotifier {
final _apiService = ApiService();
List<User> _users = [];
bool _loading = false;
String? _error;

Future<void> fetchUsers() async {
try {
_loading = true;
notifyListeners();

_users = await _apiService.getUsers();
_error = null;
} catch (e) {
_error = e.toString();
} finally {
_loading = false;
notifyListeners();
}
}
}

6. Sử Dụng Trong Widget​

class UsersScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<UserProvider>(
builder: (context, provider, child) {
if (provider._loading) {
return CircularProgressIndicator();
}

if (provider._error != null) {
return Text('Lỗi: ${provider._error}');
}

return ListView.builder(
itemCount: provider._users.length,
itemBuilder: (context, index) {
final user = provider._users[index];
return ListTile(
title: Text(user.name),
subtitle: Text(user.email),
);
},
);
},
);
}
}

7. Xử Lý Lỗi​

  • Implement try-catch blocks
  • Hiển thị thông báo lỗi phù hợp
  • Có cơ chế retry khi request thất bại
  • Xử lý các trường hợp:
    • Lỗi kết nối mạng
    • Lỗi server (500)
    • Lỗi authentication (401, 403)
    • Lỗi validation (400)

8. Best Practices​

  • Sử dụng base client để tái sử dụng code
  • Implement caching mechanism
  • Logging và monitoring
  • Unit testing cho API calls
  • Sử dụng các pattern như Repository Pattern
  • Tách biệt logic business và UI