Flutter数组对象适配插件array_object_adapter的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter数组对象适配插件array_object_adapter的使用

Adapter that is similar to the ObjectAdapter (ArrayObjectAdapter) from the Android Leanback support library.

示例项目

在示例文件夹中有一个非常棒的示例项目。查看它。或者继续阅读以快速上手。

适配器(Adapter)

ArrayObjectAdapter 是一个基于数组的数据源,它提供了对数据模型的访问,并且与项目的展示逻辑分离(通过 Presenter/PresenterSelector)。由于该适配器实现了 Dart 的流接口,你可以简单地观察数据集的变化。

adapter.listen((_) { 
    // 数据集已更改
});

build 方法中使用 StreamBuilder 来监听数据集变化:

[@override](/user/override)
Widget build(BuildContext context) {
  return StreamBuilder(
    stream: _adapter,
    builder: (context, snapshot) {},
  );
} 

呈现器(Presenter)

将呈现逻辑从适配器逻辑中分离出来。Presenter 负责创建视图/小部件并绑定对象。

以下是一个简单的例子,其中字符串被表示为文本小部件。想象一下,例如一个用户对象,它可以使用缩略图、姓名和地址等来表示。

/// 一个简单的例子,其中字符串被表示为文本小部件。
/// 但想象一下,例如一个用户对象,可以使用缩略图、姓名和地址等来表示。
class TextPresenter extends Presenter {
  [@override](/user/override)
  Widget createView(BuildContext context, Object item) {
    final value = item as String;
    return Text(value);
  }
}

要使用多种视图类型,可以使用 PresenterSelector

final classPresenterSelector = ClassPresenterSelector()
  ..addClassPresenter(int, IntPresenter())
  ..addClassPresenter(String, TextPresenter());

final adapter = ArrayObjectAdapter(presenterSelector: classPresenterSelector);

final items = <dynamic>[];
// 创建你的内容
...

adapter.setItems(items);

将适配器附加到用于显示数据的视图中:

[@override](/user/override)
Widget build(BuildContext context) {
  return ListView.separated(
    itemCount: adapter.itemCount(),
    itemBuilder: (BuildContext context, int index) {
      final item = adapter.get(index);
      final presenter = adapter.getPresenter(item);
      return presenter.createView(context, item);
    },
    separatorBuilder: (BuildContext context, int index) => Divider(),
  );
}

完整示例 Demo

以下是一个完整的示例,展示了如何使用 ArrayObjectAdapter

import 'package:array_object_adapter/array_object_adapter.dart';
import 'package:flutter/material.dart';

import 'sample_item.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Array Any Adapter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Array Any Adapter'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late ArrayObjectAdapter _adapter;

  [@override](/user/override)
  void initState() {
    _adapter = ArrayObjectAdapter(
        presenterSelector: ClassPresenterSelector()
          ..addClassPresenter(SampleItemA, SampleAPresenter())
          ..addClassPresenter(SampleItemB, SampleBPresenter())
          ..addClassPresenter(SampleItemC, SampleCPresenter(onItemClicked)));
    _seedAdapter();
    super.initState();
  }

  void onItemClicked(dynamic item) {
    print("item has been clicked: $item");
  }

  void _seedAdapter() {
    final items = <dynamic>[];
    for (int i = 0; i < 100; i++) {
      if (i % 2 == 0) {
        items.add(SampleItemA(i, 'A $i'));
      } else if (i % 3 == 0) {
        items.add(SampleItemC(i, 'C $i'));
      } else {
        items.add(SampleItemB(i, i));
      }
    }
    _adapter.setItems(items);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: ListView.separated(
            itemCount: _adapter.itemCount(),
            itemBuilder: (BuildContext context, int index) {
              final item = _adapter.get(index);
              final presenter = _adapter.getPresenter(item);
              return presenter.createView(context, item);
            },
            separatorBuilder: (BuildContext context, int index) => Divider(),
          ),
        ));
  }
}

class SampleAPresenter extends Presenter {
  [@override](/user/override)
  Widget createView(BuildContext context, Object item) {
    final value = item as SampleItemA;
    return Text(
      value.value,
      style: TextStyle(color: Colors.green),
    );
  }
}

class SampleBPresenter extends Presenter {
  [@override](/user/override)
  Widget createView(BuildContext context, Object item) {
    final value = item as SampleItemB;
    return Text(
      value.value.toString(),
      style: TextStyle(color: Colors.blue),
    );
  }
}

typedef EventHandler = void Function(dynamic item);

class SampleCPresenter extends Presenter {
  SampleCPresenter(this.callback);

  EventHandler callback;

  [@override](/user/override)
  Widget createView(BuildContext context, Object item) {
    final value = item as SampleItemC;
    return GestureDetector(
      onTap: () => callback.call(item),
      child: Text(
        value.value,
        style: TextStyle(color: Colors.red),
      ),
    );
  }
}

更多关于Flutter数组对象适配插件array_object_adapter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数组对象适配插件array_object_adapter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,array_object_adapter 并不是一个官方或广泛认可的库名。不过,基于你的问题,我猜测你可能是想询问如何在Flutter中处理数组对象并将其适配到UI组件中,例如ListView。

在Flutter中,通常使用内置的集合处理能力和ListView组件来展示数组对象。以下是一个简单的示例,展示了如何将数组对象适配到ListView中:

示例代码

首先,假设我们有一个简单的数据模型 Person

class Person {
  String name;
  int age;

  Person({required this.name, required this.age});
}

接下来,我们创建一个包含Person对象的数组,并将其适配到ListView中:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

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

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 创建一个包含Person对象的数组
  List<Person> people = [
    Person(name: 'Alice', age: 30),
    Person(name: 'Bob', age: 25),
    Person(name: 'Charlie', age: 35),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Person List'),
      ),
      body: ListView.builder(
        itemCount: people.length,
        itemBuilder: (context, index) {
          return Card(
            child: ListTile(
              leading: CircleAvatar(
                child: Text(people[index].name[0]), // 显示名字的首字母
              ),
              title: Text(people[index].name),
              subtitle: Text('Age: ${people[index].age}'),
            ),
          );
        },
      ),
    );
  }
}

代码解释

  1. 数据模型 Person

    • 定义了一个包含nameage属性的Person类。
  2. 主应用 MyApp

    • 设置了基本的Material应用配置。
  3. 主页面 MyHomePage

    • 创建一个包含Person对象的数组people
    • 使用ListView.builder构建列表视图。ListView.builder是一个高效的列表构建器,它只在需要时才构建项。
    • itemCount指定了列表中的项数。
    • itemBuilder是一个回调函数,用于构建每个列表项。它接收上下文和当前项的索引,并返回一个Widget。
  4. 列表项

    • 每个列表项使用CardListTile来展示Person对象的信息。
    • CircleAvatar用于显示名字的首字母作为头像。

这种方式非常灵活,可以轻松地适应更复杂的数据结构和UI需求。如果你需要更高级的功能,例如分页加载、下拉刷新等,可以考虑使用RefreshIndicator和分页逻辑来扩展这个基础示例。

回到顶部