Bloc10
RepositoryProvider¶
Code¶
//main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'repository_bloc.dart';
import 'repository.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RepositoryProvider(
create: (context) => YourRepository(),
child: BlocProvider(
create: (context) =>
YourBloc(repository: context.read<YourRepository>()),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: BlocBuilder<YourBloc, YourState>(
builder: (context, state) {
if (state is YourLoading) {
return CircularProgressIndicator();
} else if (state is YourLoaded) {
return Text(state.data);
} else if (state is YourError) {
return Text('Error');
} else {
return Text('Press button to fetch data');
}
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<YourBloc>().add(FetchData()),
child: Icon(Icons.download),
),
);
}
}
程式碼解釋¶
這段程式碼是一個使用Flutter框架和Bloc模式的應用程式的主要入口點。
首先,我們在main函數中啟動了應用程式,並將MyApp作為根widget。
MyApp是一個StatelessWidget,它的build方法返回一個RepositoryProvider。RepositoryProvider是一種特殊的widget,它可以讓你在widget樹中的任何地方獲取到YourRepository的實例。
在RepositoryProvider的child參數中,我們放置了一個BlocProvider。BlocProvider也是一種特殊的widget,它可以讓你在widget樹中的任何地方獲取到YourBloc的實例。在創建YourBloc時,我們從context中讀取了YourRepository的實例並將其傳遞給YourBloc。
BlocProvider的child參數是一個MaterialApp,這是應用程式的主要widget。它包含了應用程式的主題數據和首頁。
首頁是一個MyHomePage widget,這也是一個StatelessWidget。在其build方法中,我們創建了一個Scaffold,這是一個基本的布局widget,它提供了一個app bar和一個body。
在body中,我們使用了BlocBuilder來根據YourBloc的狀態來構建不同的widget。如果狀態是YourLoading,我們顯示一個進度指示器;如果狀態是YourLoaded,我們顯示一個包含數據的文本;如果狀態是YourError,我們顯示一個”Error”的文本;在其他情況下,我們顯示一個”Press button to fetch data”的文本。
我們還添加了一個浮動動作按鈕,當按下時,它會觸發FetchData事件,這將導致YourBloc從YourRepository獲取數據。
//lib\repository.dart
class YourRepository {
Future<String> fetchData() async {
// 這裡是你的資料取得邏輯,例如從API或本地資料庫取得資料
// 在這個範例中,我們只是簡單地回傳一個字串
await Future.delayed(Duration(seconds: 1)); // 模擬網路延遲
String currentTime = DateTime.now().toString();
return 'Hello, World! Current time: $currentTime';
}
}
程式碼解釋¶
這段程式碼定義了一個名為YourRepository的類別,該類別有一個名為fetchData的方法。這個方法是異步的,意味著它將返回一個Future,這個Future在未來某個時間點將會完成並返回一個字符串。
在fetchData方法中,我們首先使用Future.delayed來模擬網路延遲。這個方法會創建一個新的Future,並在指定的延遲時間(在這個例子中是1秒)後完成。
然後,我們使用DateTime.now來獲取當前的時間,並將其轉換為字符串。這個字符串將被添加到”Hello, World! Current time: “後面,並作為fetchData方法的返回值。
這個YourRepository類別可以被用來從API或本地資料庫獲取數據。在這個範例中,我們只是簡單地回傳一個包含當前時間的字符串,但在實際的應用程式中,你可能需要在這裡實現更複雜的邏輯。
//lib\repository_bloc.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'repository.dart';
class YourBloc extends Bloc<YourEvent, YourState> {
final YourRepository repository;
YourBloc({required this.repository}) : super(YourInitial()) {
on<FetchData>((event, emit) async {
emit(YourLoading());
try {
final data = await repository.fetchData();
emit(YourLoaded(data: data));
} catch (_) {
emit(YourError());
}
});
}
}
abstract class YourEvent {}
class FetchData extends YourEvent {}
abstract class YourState {}
class YourInitial extends YourState {}
class YourLoading extends YourState {}
class YourLoaded extends YourState {
final String data;
YourLoaded({required this.data});
}
class YourError extends YourState {}
程式碼解釋¶
這段程式碼是使用flutter_bloc套件來實現Bloc模式的一個範例。Bloc模式是一種用於管理應用程式狀態的模式,它將事件(event)作為輸入,並產生狀態(state)作為輸出。
在這段程式碼中,我們首先定義了一個名為YourBloc的Bloc。這個Bloc有一個YourRepository的實例,這個實例在Bloc被創建時通過構造函數傳入。Bloc的初始狀態被設定為YourInitial。
然後,我們為Bloc註冊了一個事件處理器,這個處理器對應FetchData事件。當這個事件被觸發時,Bloc會首先發出YourLoading狀態,然後嘗試從YourRepository獲取數據。如果數據獲取成功,Bloc會發出YourLoaded狀態並將數據作為參數傳入;如果數據獲取失敗,Bloc會發出YourError狀態。
最後,我們定義了一些事件和狀態的類別。這些類別代表了Bloc可以處理的事件和可以發出的狀態。在這個範例中,我們定義了FetchData事件,以及YourInitial、YourLoading、YourLoaded和YourError狀態。
一個很醜的範例¶
請幫我把它變美
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:http/http.dart';
import 'dart:convert';
void main() {
runApp(const MaterialApp(
home: Scaffold(body: UsersPage()),
));
}
class UsersRepository {
Future<List<User>> getUsers() async {
final response =
await get(Uri.parse('https://jsonplaceholder.typicode.com/users'));
if (response.statusCode == 200) {
final users = json.decode(response.body) as List;
return users.map((user) => User.fromJson(user)).toList();
} else {
throw Exception('Error fetching users');
}
}
}
class User {
final int? id;
final String? name;
final String? email;
User({this.id, this.name, this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
}
class UsersBloc extends Bloc<UsersEvent, UsersState> {
final UsersRepository usersRepository;
UsersBloc({required this.usersRepository}) : super(UsersInitial()) {
on<UsersFetched>((event, emit) async {
try {
final users = await usersRepository.getUsers();
emit(UsersLoaded(users: users));
} catch (e) {
emit(UsersError(error: e.toString()));
}
});
}
}
abstract class UsersEvent {}
class UsersFetched extends UsersEvent {}
abstract class UsersState {}
class UsersInitial extends UsersState {}
class UsersLoaded extends UsersState {
final List<User> users;
UsersLoaded({required this.users});
}
class UsersError extends UsersState {
final String error;
UsersError({required this.error});
}
class UsersPage extends StatelessWidget {
const UsersPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) {
final bloc = UsersBloc(usersRepository: UsersRepository());
bloc.add(UsersFetched()); // 觸發事件來獲取用戶數據
return bloc;
},
child: BlocBuilder<UsersBloc, UsersState>(
builder: (context, state) {
if (state is UsersError) {
return Center(
child: Text(state.error),
);
} else if (state is UsersLoaded && state.users.isEmpty) {
return Center(
child: const CircularProgressIndicator(),
);
} else if (state is UsersLoaded) {
return ListView.builder(
itemCount: state.users.length,
itemBuilder: (context, index) {
final user = state.users[index];
return ListTile(
title: Text(user.name!),
subtitle: Text(user.email!),
);
},
);
} else {
return Container();
}
},
),
);
}
}
Created : 13 novembre 2024