Flutter远程状态管理插件remote_state的使用

Flutter远程状态管理插件remote_state的使用

RemoteState

Build & test codecov License: MIT

工具用于在Dart中映射来自远程源的数据,类似于Elm的RemoteData: https://elmprogramming.com/remote-data.html

Package Pub
remote_state pub package

Slaying a UI Antipattern with Flutter

受Kris Jenkins博客文章启发,关于如何通过Elm解决UI反模式问题。

What problem does this package solve?

你正在发起一个API请求,并希望根据请求的状态显示或执行不同的操作。

Why RemoteState, not RemoteData?

我在Jed Watson的一次演讲中获得了次要灵感,演讲主题为《论状态》。尽可能地在我的应用中正确分类状态。

The RemoteState approach

我们使用单一数据类型来表达所有可能的请求状态,而不是使用复杂对象。这种做法使得创建无效状态变得不可能。

Usage

RemoteState的一个常见用例是将其映射到UI过渡或组件状态。以下是一个使用StateNotifier的示例,可以在examples/counter_state_notifier目录下找到:

counter/notifier/counter.dart

class CounterNotifier extends StateNotifier<RemoteState<int>> {
  var _counterClient = CounterClient();

  CounterNotifier() : super(RemoteState.initial()) {
    getCount();
  }

  getCount() async {
    state = RemoteState.loading();

    state = await RemoteState.guard(() => _counterClient.getCount());
  }

  increment() async {
    state = await RemoteState.guard(() => _counterClient.increment());
  }

  decrement() async {
    state = await RemoteState.guard(() => _counterClient.decrement());
  }
}

main.dart

class ExampleApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: StateNotifierProvider<CounterNotifier, RemoteState<int>>.value(
        value: CounterNotifier(),
        child: HomePage(),
      ),
    );
  }
}

home.dart

class HomePage extends StatelessWidget {
  const HomePage({Key key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    //2. 解析计数器通知器以更新状态
    var counterNotifier = Provider.of<CounterNotifier>(context);
    var counterState = Provider.of<RemoteState<int>>(context);

    var textStyle = Theme.of(context).textTheme.headline4;
    final fabPadding = EdgeInsets.symmetric(vertical: 5.0);

    return Scaffold(
      appBar: AppBar(
        title: Text('RemoteState with StateNotifier'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            //3. 渲染状态变化
            counterState.when(
              initial: () => Text('Not loaded', style: textStyle),
              success: (value) => Text('$value', style: textStyle),
              loading: () => Text('Loading...', style: textStyle),
              error: (_) => Text('Error', style: textStyle),
            ),
          ],
        ),
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Padding(
            padding: fabPadding,
            child: FloatingActionButton(
              heroTag: 'inc',
              child: Icon(Icons.add),
              //4. 执行递增操作
              onPressed: () => counterNotifier.increment(),
            ),
          ),
          Padding(
            padding: fabPadding,
            child: FloatingActionButton(
              heroTag: 'dec',
              child: Icon(Icons.remove),
              //5. 执行递减操作
              onPressed: () => counterNotifier.decrement(),
            ),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter远程状态管理插件remote_state的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter远程状态管理插件remote_state的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用remote_state插件进行远程状态管理的代码示例。remote_state插件允许你从远程服务器获取状态并在Flutter应用中管理这些状态。尽管remote_state并不是Flutter官方或广泛使用的插件(可能是一个假设的插件名或特定团队的自定义插件),但我会基于远程状态管理的概念给出一个示例,使用类似功能的实现。

在实际场景中,你可能会使用像providerriverpodget_it等状态管理库结合HTTP请求库(如diohttp)来实现远程状态管理。下面是一个使用providerhttp库实现远程状态管理的示例。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加必要的依赖:

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0
  http: ^0.13.3

2. 创建远程数据模型

假设你有一个远程API返回如下JSON数据:

{
  "status": "active",
  "data": {
    "username": "exampleUser",
    "email": "example@example.com"
  }
}

你可以创建一个数据模型来匹配这个结构:

class RemoteStatus {
  String status;
  Data data;

  RemoteStatus({required this.status, required this.data});

  factory RemoteStatus.fromJson(Map<String, dynamic> json) {
    return RemoteStatus(
      status: json['status'] as String,
      data: Data.fromJson(json['data'] as Map<String, dynamic>),
    );
  }
}

class Data {
  String username;
  String email;

  Data({required this.username, required this.email});

  factory Data.fromJson(Map<String, dynamic> json) {
    return Data(
      username: json['username'] as String,
      email: json['email'] as String,
    );
  }
}

3. 创建状态提供者

使用provider库创建一个状态提供者来管理远程数据:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class RemoteStatusProvider with ChangeNotifier {
  RemoteStatus? _remoteStatus;
  RemoteStatus? get remoteStatus => _remoteStatus;

  RemoteStatusProvider() {
    fetchRemoteStatus();
  }

  void fetchRemoteStatus() async {
    try {
      final response = await http.get(Uri.parse('https://api.example.com/status'));
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        _remoteStatus = RemoteStatus.fromJson(data);
        notifyListeners();
      } else {
        throw Exception('Failed to load remote status');
      }
    } catch (error) {
      print('Error fetching remote status: $error');
    }
  }
}

4. 在应用中使用提供者

在你的MaterialApp中使用MultiProvider来提供RemoteStatusProvider

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'remote_status_provider.dart'; // 假设你的提供者文件名为remote_status_provider.dart

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => RemoteStatusProvider()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Remote State Management',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

5. 显示远程状态

在你的主页面中使用Consumer来访问和显示远程状态:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'remote_status_model.dart'; // 假设你的数据模型文件名为remote_status_model.dart

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Remote Status'),
      ),
      body: Consumer<RemoteStatusProvider>(
        builder: (context, provider, child) {
          final remoteStatus = provider.remoteStatus;
          if (remoteStatus == null) {
            return Center(child: CircularProgressIndicator());
          }
          return Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Status: ${remoteStatus.status}'),
                SizedBox(height: 16),
                Text('Username: ${remoteStatus.data!.username}'),
                Text('Email: ${remoteStatus.data!.email}'),
              ],
            ),
          );
        },
      ),
    );
  }
}

这个示例展示了如何使用providerhttp库在Flutter中实现远程状态管理。你可以根据需要调整代码以适应你的具体需求和API结构。如果你提到的remote_state插件有特定的API或用法,请参考其官方文档进行实现。

回到顶部