Skip to content

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方法返回一個RepositoryProviderRepositoryProvider是一種特殊的widget,它可以讓你在widget樹中的任何地方獲取到YourRepository的實例。

RepositoryProviderchild參數中,我們放置了一個BlocProviderBlocProvider也是一種特殊的widget,它可以讓你在widget樹中的任何地方獲取到YourBloc的實例。在創建YourBloc時,我們從context中讀取了YourRepository的實例並將其傳遞給YourBloc

BlocProviderchild參數是一個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事件,這將導致YourBlocYourRepository獲取數據。


//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事件,以及YourInitialYourLoadingYourLoadedYourError狀態。

一個很醜的範例

請幫我把它變美

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();
          }
        },
      ),
    );
  }
}

Last update : 13 novembre 2024
Created : 13 novembre 2024

Comments

Comments