Flutter数据流展示插件stream_feed的使用
Flutter数据流展示插件stream_feed的使用
官方Dart客户端
官方Dart客户端用于Stream活动流服务,该服务用于构建Feed应用程序。此库可用于任何Dart项目,并且可以在带有Flutter的移动和Web应用中集成。
快速链接
- 注册以获取Stream活动流的API密钥
- 教程学习如何设置时间线Feed、关注其他Feed并发布新活动。
- Stream活动流UI工具包可帮助您快速启动通知和社交Feed的设计。
安装
从pub安装
dependencies:
flutter:
sdk: flutter
stream_feed: ^[最新版本]
使用与Flutter集成
此软件包可以集成到Flutter应用程序中。记住不要在Flutter Web应用、移动应用或其他不受信任的环境中(如桌面应用)暴露App Secret。
使用
API客户端设置(服务器端+客户端)
如果您想直接在Web/移动应用中使用API客户端,则需要生成用户令牌并在客户端传递。
服务器端令牌生成
// 实例化一个新的客户端(服务器端)
const apiKey = '我的API密钥';
const secret = '我的API秘密';
// 实例化一个新的客户端(服务器端)
var client = StreamFeedClient(apiKey, secret: secret, runner: Runner.server);
// 可选地提供应用程序标识符和指定数据中心位置和请求超时选项的对象(15秒)
client = StreamFeedClient(apiKey,
secret: secret,
runner: Runner.server,
appId: 'yourappid',
runner: Runner.server,
options: StreamHttpClientOptions(
location: Location.usEast,
connectTimeout: Duration(seconds: 15),
),
);
// 为用户id为 "the-user-id" 的用户创建一个令牌
final userToken = client.frontendToken('the-user-id');
⚠️ 注意:出于安全考虑,您绝不能暴露您的API密钥或生成的客户端侧令牌,强烈建议在客户端侧令牌中使用 exp
声明。
客户端API初始化
// 实例化新的客户端并设置用户令牌
var client = StreamFeedClient(apiKey);
await client.setUser(user: user, token: frontendToken);
示例
示例项目
有一个详细的Flutter示例项目位于此处。您可以直接运行并进行测试。
示例代码
import 'dart:io';
import 'package:stream_feed/stream_feed.dart';
Future<void> main() async {
final env = Platform.environment;
final secret = env['secret'];
final apiKey = env['apiKey'];
final appId = env['appId'];
final clientWithSecret = StreamFeedClient(
apiKey!,
secret: secret,
runner: Runner.server,
);
final chris = clientWithSecret.flatFeed('user', 'chris');
// 添加活动;message是自定义字段
// 提示:您可以添加无限数量的自定义字段!
final addedPicture = await chris.addActivity(
const Activity(
actor: 'chris',
verb: 'add',
object: 'picture:10',
foreignId: 'picture:10',
extraData: {'message': 'Beautiful bird!'},
),
);
// 在Jack的"timeline" Feed和Chris的"user" Feed之间创建一个关注关系:
final jack = clientWithSecret.flatFeed('timeline', 'jack');
await jack.follow(chris);
// 阅读Jack的timeline,Chris的帖子会出现在feed中:
final results = await jack.getActivities(limit: 10);
// 通过引用其Foreign Id来删除一个活动:
await chris.removeActivityByForeignId('picture:10');
// 使用feed组'user'和用户id '1'实例化一个feed
final user1 = clientWithSecret.flatFeed('user', '1');
// 创建一个活动对象
var activity = const Activity(actor: 'User:1', verb: 'pin', object: 'Place:42');
// 向feed中添加一个活动
final pinActivity = await user1.addActivity(activity);
// 创建一个更复杂的活动
activity = Activity(
actor: 'User:1',
verb: 'run',
object: 'Exercise:42',
extraData: {
'course': {'name': 'Golden Gate park', 'distance': 10},
'participants': ['Thierry', 'Tommaso'],
'started_at': DateTime.now().toIso8601String(),
'foreign_id': 'run:1',
'location': {'type': 'point', 'coordinates': [37.769722, -122.476944]}
}
);
final exercise = await user1.addActivity(activity);
// 获取5个id小于给定UUID的活动(更快 - 推荐!)
var response = await user1.getActivities(
limit: 5,
filter: Filter().idLessThan('e561de8f-00f1-11e4-b400-0cc47a024be0'),
);
// 从5到10获取活动(分页 - 较慢)
response = await user1.getActivities(offset: 0, limit: 5);
// 按排名排序获取活动(启用排名Feed):
// response = await userFeed.getActivities(limit: 5, ranking: "popularity"); //必须启用
// 服务器端
var client = StreamFeedClient(
apiKey,
secret: secret,
appId: appId,
runner: Runner.server,
options: const StreamHttpClientOptions(location: Location.usEast),
);
final userToken = client.frontendToken('user.id');
// 客户端侧
client = StreamFeedClient(
apiKey,
appId: appId,
);
// 通过id删除一个活动
await user1.removeActivityById(addedPicture.id!);
// 通过foreign_id 'run:1' 删除活动
await user1.removeActivityByForeignId('run:1');
final now = DateTime.now();
activity = Activity(
actor: '1',
verb: 'like',
object: '3',
time: now,
foreignId: 'like:3',
extraData: {'popularity': 100});
// 第一次添加活动
final like = await user1.addActivity(activity);
// 向API发送更新
user1.updateActivityById(id: like.id!,
// 更新活动的popularity值
set: {'popularity': 10});
// 部分更新活动ID
await user1.updateActivityById(id: exercise.id!, set: {
'course.distance': 12,
'shares': {
'facebook': '...',
'twitter': '...'
}
}, unset: ['location', 'participants']);
// 部分更新foreign ID
// user1.updateActivityByForeignId(
// foreignId: 'product:123',
// time: DateTime.parse(('2016-11-10T13:20:00.000000'),
// set: {
// ...
// },
// unset: [
// ...
// ]
// );
// 批量部分更新 TODO
// final now = DateTime.now();
final firstActivity = Activity(
actor: '1',
verb: 'add',
object: '1',
foreignId: 'activity_1',
time: DateTime.now(),
);
// 向活动feed添加活动
final firstActivityAdded = await user1.addActivity(firstActivity);
final secondActivity = Activity(
actor: '1', verb: 'add', object: '1', foreignId: 'activity_2', time: now);
final secondActivityAdded = await user1.addActivity(secondActivity);
// 关注Feed
// timeline:timeline_feed_1 关注 user:user_42:
final timelineFeed1 = clientWithSecret.flatFeed('timeline', 'timeline_feed_1');
final user42feed = clientWithSecret.flatFeed('user', 'user_42');
await timelineFeed1.follow(user42feed);
// 不复制活动的关注Feed
await timelineFeed1.follow(user42feed, activityCopyLimit: 0);
// 取消关注Feed
// 停止关注user_42 - 清除历史记录:
await timelineFeed1.unfollow(user42feed);
// 停止关注user_42但保留已发布的活动历史:
await timelineFeed1.unfollow(user42feed, keepHistory: true);
// 读取Feed的追随者
// 列出追随者
await user1.followers(limit: 10, offset: 10);
// 获取最后10个由user_feed_1关注的Feed
await user1.following(offset: 0, limit: 10);
// 从第11个开始获取由user_feed_1关注的10个Feed
await user1.following(offset: 10, limit: 10);
// 检查user1是否关注特定的Feed
await user1.following(
offset: 0,
limit: 2,
filter: [FeedId.id('user:42'), FeedId.id('user:43')]);
// 获取Feed的追随者和被关注者的统计信息
await clientWithSecret.flatFeed('user', 'me').followStats();
// 获取Feed的追随者和被关注者的统计信息,还可以使用给定的slugs过滤
// 统计有多少个timeline关注我
// 统计有多少个markets被关注
await clientWithSecret
.flatFeed('user', 'me')
.followStats(followerSlugs: ['timeline'], followingSlugs: ['market']);
// 实时
final frontendToken = clientWithSecret.frontendToken('john-doe');
// 使用场景:提及
// 将活动添加到Eric的Feed和Jessica的通知Feed
activity = Activity(
actor: 'user:Eric',
extraData: {'message': '@Jessica check out getstream.io it\'s awesome!'},
verb: 'tweet',
object: 'tweet:id',
to: [FeedId.id('notification:Jessica')],
);
final tweet = await user1.addActivity(activity);
// 对活动id添加一个like反应
await clientWithSecret.reactions.add('like', tweet.id!, userId: 'userId');
// 添加一个评论反应到活动id
await clientWithSecret.reactions.add('comment', tweet.id!,
data: {'text': 'awesome post!'}, userId: 'userId');
// 对于服务器端身份验证,userId是必需的
final comment = await clientWithSecret.reactions.add('comment', tweet.id!,
data: {'text': 'awesome post!'}, userId: 'userId');
// 首先让我们阅读当前用户的timeline Feed并选择一个活动
final activities = await clientWithSecret.flatFeed('user', '1').getActivities();
// 然后让我们对该活动添加一个like反应
final otherLike = await clientWithSecret.reactions
.add('like', activities.first.id!, userId: 'userId');
// 检索活动的所有类型的反应
await clientWithSecret.reactions.filter(
LookupAttribute.activityId, '5de5e4ba-add2-11eb-8529-0242ac130003');
// 检索活动的前10个like
await clientWithSecret.reactions.filter(
LookupAttribute.activityId, '5de5e4ba-add2-11eb-8529-0242ac130003',
kind: 'like', limit: 10);
// 使用id_lt参数检索下一个10个like
await clientWithSecret.reactions.filter(
LookupAttribute.activityId,
'5de5e4ba-add2-11eb-8529-0242ac130003',
kind: 'like',
filter: Filter().idLessThan('e561de8f-00f1-11e4-b400-0cc47a024be0'),
);
}
更多关于Flutter数据流展示插件stream_feed的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数据流展示插件stream_feed的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用stream_feed
插件来展示数据流的示例代码。这个示例假设你已经安装并配置好了stream_feed
插件以及任何必要的依赖项。
首先,确保你的pubspec.yaml
文件中包含stream_feed
依赖项:
dependencies:
flutter:
sdk: flutter
stream_feed: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
接下来,我们将创建一个简单的Flutter应用,使用stream_feed
来展示数据流。以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'package:stream_feed/stream_feed.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Stream Feed Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: StreamFeedScreen(),
);
}
}
class StreamFeedScreen extends StatefulWidget {
@override
_StreamFeedScreenState createState() => _StreamFeedScreenState();
}
class _StreamFeedScreenState extends State<StreamFeedScreen> {
// 模拟数据流
List<StreamFeedItem> _feedItems = [
StreamFeedItem(
id: '1',
user: StreamFeedUser(
id: 'user1',
name: 'Alice',
avatarUrl: 'https://via.placeholder.com/150',
),
content: 'Hello, this is a test post!',
timestamp: DateTime.now().subtract(Duration(days: 1)),
likes: 5,
comments: 2,
imageUrl: 'https://via.placeholder.com/600x400',
),
StreamFeedItem(
id: '2',
user: StreamFeedUser(
id: 'user2',
name: 'Bob',
avatarUrl: 'https://via.placeholder.com/150',
),
content: 'Another test post!',
timestamp: DateTime.now().subtract(Duration(hours: 2)),
likes: 10,
comments: 3,
),
// 可以添加更多项目
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stream Feed Demo'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: StreamFeed(
items: _feedItems,
onItemClicked: (item) {
// 处理点击事件
print('Item clicked: ${item.content}');
},
onLikeClicked: (item) {
// 处理点赞事件
setState(() {
item.likes += 1;
});
},
onCommentClicked: (item) {
// 处理评论事件
setState(() {
item.comments += 1;
});
},
),
),
);
}
}
// 定义 StreamFeedItem 和 StreamFeedUser 模型(如果插件没有自带的话)
class StreamFeedItem {
final String id;
final StreamFeedUser user;
final String content;
final DateTime timestamp;
final int likes;
final int comments;
final String? imageUrl;
StreamFeedItem({
required this.id,
required this.user,
required this.content,
required this.timestamp,
required this.likes,
required this.comments,
this.imageUrl,
});
}
class StreamFeedUser {
final String id;
final String name;
final String avatarUrl;
StreamFeedUser({
required this.id,
required this.name,
required this.avatarUrl,
});
}
说明:
- 依赖项:确保在
pubspec.yaml
中添加了stream_feed
依赖项。 - 数据模型:定义了
StreamFeedItem
和StreamFeedUser
模型来表示数据流中的项和用户信息。实际使用中,这些模型可能会根据stream_feed
插件的具体要求有所不同。 - UI构建:在
StreamFeedScreen
中,使用StreamFeed
组件来展示数据流,并处理点击、点赞和评论事件。 - 事件处理:在
StreamFeed
组件中,通过回调函数处理点击、点赞和评论事件,更新UI状态。
这个示例展示了如何使用stream_feed
插件来展示一个简单的数据流,并处理用户交互。根据你的具体需求,你可以进一步扩展和自定义这个示例。