Flutter社交应用模板插件social_app_template的使用

Flutter社交应用模板插件social_app_template的使用

源码

源码可以在GitLab上找到。

特性

您可以使用一组用于您的社交媒体应用程序的小部件、存储库和模型。

带有帖子的列表

目前,这是该包的根小部件。查看进一步说明以了解将移至新根小部件的未来小部件。

此列表由一个无限分页的帖子列表组成,每页包含7个项目。当用户滚动并到达第6个帖子时,会自动加载更多帖子。

  • 预定义的对象模型如用户、帖子、媒体或位置。
  • 已实现完整的数据库(在IsarDB中实现)及所有所需的CRUD操作。
  • 无限可分页的帖子列表。
  • 图片和视频将被缓存。
  • 列表中的所有视频将自动播放并在可见度低于40%时停止。

由于大量的用户生活在网速较慢的地区,或者他们可能拥有低速WiFi或希望节省移动数据,所有视频都包含PerformanceIndicator,这将向用户展示下载的质量是否符合配置的质量。配置对应的开关将在下一个版本中实现。

开始使用

pubspec.yaml文件中添加依赖:

dependencies:
  social_app_template: ^1.0.0

然后在项目文件夹的控制台中运行:

flutter pub get

前提条件:

environment:
  sdk: ">=2.12.0 <3.0.0"

使用

您可以使用此包提供的小部件和功能通过SocialApp接口访问。此外,您还可以直接访问大多数类,如存储库、模型类和服务。

构建带有帖子的列表

请注意为媒体对象提供尺寸(参见存储库以获取更多信息)。否则,列表将需要一些毫秒来加载。首先,它会计算图像的大小以进行渲染。

提供的尺寸将允许无缝滚动,同时固定尺寸。这也将启用适当的内存大小缓存。

您可以通过调用SocialApp.postList创建一个带有帖子的列表。你应该把它放在一个具有约束条件的容器中,因为它仍然是一个需要约束条件的列表。

你可以通过用户下拉刷新指定onRefresh函数。

@override
Widget build(BuildContext context){
    final size = MediaQuery.of(context).size;
    
    final postIds = ['post_0', 'post_1'];
    
    return SizedBox(
      width: size.width,
      height: size.height,
      child: SocialApp.postList(
        ids: postIds,
        onRefresh: _onRefresh,
      ),
    );

    List<PlatformPost> _onRefresh() {
      return ['post_2', 'post_3'];
    }
}

如果需要调整帖子的附加信息或在渲染前验证帖子,可以使用onInitPost

@override
Widget build(BuildContext context){
    final size = MediaQuery.of(context).size;
    
    final postIds = ['post_0', 'post_1'];
    
    return SizedBox(
      width: size.width,
      height: size.height,
      child: SocialApp.postList(
        ids: postIds,
        onInitPost: _onInitPost,
      ),
    );

    Future<PlatformPost?> _onInitPost(PlatformPost post) async {
      final postWithMySocialMediaApiDetails = await MySocialMediaApi().getPostDetails();
      post.media.addAll(postWithMySocialMediaApiDetails.images);
      return post;
    }
}

如果需要带有进度指示器的列表,可以使用SocialApp.postListWithProgress

@override
Widget build(BuildContext context){
    final size = MediaQuery.of(context).size;
    
    final postIds = ['post_0', 'post_1'];
    final progressAlignment = const Alignment(0.5, -0.85);
    
    return SizedBox(
      width: size.width,
      height: size.height,
      child: SocialApp.postListWithProgress(
        ids: postIds,
        progressAlignment: progressAlignment,
      ),
    );
}

存储库

此包提供了您可能需要的所有CRUD操作的现有模型类。现有的数据库是一种非常快速的数据库,可以处理数百万个对象的存储,这些对象还支持关系和非常具体的查询。

自定义存储库

您也可以使用IsarDB.isar实例创建自己的存储库。只需参考现有代码或探索Isar文档

以下自定义存储库的示例需要在项目文件夹中运行flutter pub run build_runner build

因此,暂时需要在pubspec.yaml中添加以下依赖项:

dev_dependencies:
  ...
  isar_generator: ^3.0.5
  build_runner: any

在存储库中,您可以使用IsarDB.isar实例实现所有所需的CRUD操作。

class MyRepository {
  Future<void> create(MyObject){
    await IsarDB.isar.writeTxn(
            () => IsarDB.isar.myObjects.create(),
    );
  }
  
  Future<List<MyObject>> getAllById(Id id){
    return IsarDB.isar.myObjects
        .where().idEqualsTo(id)
        .findAll();
  }
}

模型对象应该有一个名称作为上面示例中create函数中使用的访问器。

此外,Id属性是必需的,作为生成的part,您需要运行flutter pub run build_runner build来生成。

part 'my_object.g.dart';

@Collection(accessor: 'myObjects')
class MyObject {
  Id? id;
}

在生成my_object.g.dart文件后,现在可以将创建的适配器传递给根小部件。

@override
Widget build(BuildContext context){
  final size = MediaQuery.of(context).size;

  final postIds = ['post_0', 'post_1'];

  return SizedBox(
    width: size.width,
    height: size.height,
    child: SocialApp.postList(
      ids: postIds,
      furtherSchema: [MyObjectSchema],
    ),
  );
}

SocialApp模板的存储库

现有的存储库可以直接调用而无需使用SocialApp接口,如以下示例所示。

PlatformPostRepository

管理PlatformPost模型对象的存储库,用于您实现的社交媒体的帖子。

PlatformPost应该有一个作者(有关更多信息,请参阅PlatformUserRepository)。无论如何,作者属性未标记为必需。如果没有链接的作者,您将无法在PostInList小部件中看到作者的个人资料图像和姓名。

您可以包括urlshashtagsuserMentionsmedia等信息,通过使用PlatformPostEntities

void main async {
    final posts =  List.generate(
      2,
          (index) => PlatformPost.of(
              id: '$index',
              entities: PlatformPostEntities.of(
                postId: '$index',
                urls: [
                  'https://mysocialmedia.web/profile/1234'
                ],
                hashtags: [
                  'apple',
                  'fruit',
                ],
                media: [PlatformMedia(
                  id: 'media_0',
                  url: 'https://mysocialmedia.web/image/media_0',
                )],
              )
          ),
    );
  
    await PlatformPostRepository.createAll(posts);
    
    final allCreatedPosts = await PlatformPostRepository.getAll();
    
    /// 应打印2个帖子
    print(allCreatedPosts.map((post) => '${post.id}\n').toList());
    
    runApp(myApp());
}

PlatformUserRepository

管理PlatformUser模型对象的存储库,用于您实现的社交媒体的用户。

该模型允许您存储用户的地点作为LocationQuery(有关更多信息,请参阅LocationQueryRepository)。

您应该始终在调用PlatformPostRepository.create时优先创建用户作为嵌入对象。在以下示例中,作者和提及用户将与帖子对象一起持久化和创建到数据库中。

void main async {
  
    final author = PlatformUser.of(
      id: 'user_0',
      name: 'user_name',
      profileImageUrl: 'https://mysocialmedia.web/images/profile/user_0'
    ); 
    
    final mentionedUser = PlatformUser.of(
      id: 'user_1',
      name: 'user_name',
      profileImageUrl: 'https://mysocialmedia.web/images/profile/user_1'
    );
    
    final post =  PlatformPost.of(
              id: 'post_0',
              user: author,
              entities: PlatformPostEntities.of(
                  postId: '$index',
                  userMentions: [mentionedUser],
              )
          );
  
    await PlatformPostRepository.create(post);
    
    final users = await PlatformUserRepository.getAllBy(ids: ['user_0','user_1']);
    
    /// 应打印2个用户
    print(users.map((user) => '${user.id}\n').toList());
    
    runApp(myApp());
}

但是,您仍然可以在不将其作为嵌入对象创建的情况下创建和获取用户,通过PlatformUserRepository.create

void main async {
  
    final user = PlatformUser.of(
      id: 'user_0',
      name: 'user_name',
      profileImageUrl: 'https://mysocialmedia.web/images/profile/user_0'
    );
    
    await PlatformUserRepository.create(user);
    
    final storedUser = await PlatformUserRepository.getAsync('user_0');
   
    /// 应打印1个用户
    print('${storedUser?.id}\n');
    
    runApp(myApp());
}

LocationQueryRepository

管理LocationQuery模型对象的存储库,用于您实现的社交媒体的位置。

位置包含以下属性:

  • query -> 文本表示的位置
  • latitude -> 位置的纬度
  • longitude -> 位置的经度
  • address -> 位置的地址

该模型允许您存储用户的地址作为MapBoxPlace对象模型。

  • 由于在我的应用程序中,我从mapbox.com获取位置信息,因此该对象的结构和名称受mapbox启发。
  • 在未来的版本中,您还将能够从mapbox获取地址。
void main async {
    final location = LocationQuery.of(
      id: 0,
      query: 'Berlin',
      latitude: 52.0,
      longitude: 13.0,
      address: MapBoxPlace.of(
        id: 'place_0',
        text: 'Lindenallee',
        placeName: 'Zentrum, Berlin',
        context: [
          MapBoxPlaceContext(
            id: 'country_place_0',
            mapBoxPlaceId: 'place_0',
            text: 'Germany',
          ),
          MapBoxPlaceContext(
            id: 'city_place_0',
            mapBoxPlaceId: 'place_0',
            text: 'Berlin',
          ),
        ],
      ),
    );
    
    await LocationQueryRepository.create(location);
    
    final locations = await LocationQueryRepository.getByQueryAsync('Berlin');
    
    /// 应打印1个位置
    print(locations.map((location) => '${location.query}\n').toList());
    
    runApp(myApp());
}

正如在PlatformUserRepository中提到的,您应该通过其父对象创建嵌入对象。相同的规则也适用于位置。

因此,MapBoxPlace及其上下文MapBoxPlaceContext也将作为嵌入对象自动持久化和创建到数据库中。

例如:

  • 当您为用户创建位置时,应使用PlatformUserRepository.create
  • 当您为用户在帖子中创建位置时,应使用PlatformPostRepository.create
void main async {
    final location = LocationQuery.of(
     ...
      address: MapBoxPlace.of(
        ...
        context: [
          MapBoxPlaceContext(
           ...
          ),
          MapBoxPlaceContext(
            ...
          ),
        ],
      ),
    );
    
    final user = PlatformUser.of(
        id: 'user_0',
        location: location,
    );
    
    await PlatformUserRepository.create(user);
    
    final storedUser = await PlatformUserRepository.getAsync('user_0');
    
    /// 应打印1个位置
    print('${storedUser?.location?.value?.query}\n');

    runApp(myApp());
}

更多关于Flutter社交应用模板插件social_app_template的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter社交应用模板插件social_app_template的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于使用Flutter的social_app_template插件来创建一个社交应用模板,下面是一个基本的代码示例和说明,帮助你快速上手。请注意,social_app_template并不是一个官方或广泛认可的Flutter插件,因此以下示例将基于一个假设的插件结构和功能。在实际项目中,你可能需要参考具体的插件文档进行调整。

首先,确保你的Flutter环境已经设置好,并且你已经创建了一个新的Flutter项目。

1. 添加依赖

pubspec.yaml文件中添加social_app_template(假设它存在于pub.dev或者你的私有包仓库中):

dependencies:
  flutter:
    sdk: flutter
  social_app_template: ^x.y.z  # 替换为实际的版本号

然后运行flutter pub get来安装依赖。

2. 初始化插件

在你的main.dart文件中,初始化并使用social_app_template插件。这里假设插件提供了一个SocialApp小部件来快速启动社交应用模板:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Social App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SocialApp(
        // 假设SocialApp小部件接受一些配置参数
        apiKey: 'your_api_key', // 替换为你的API密钥
        endpoint: 'https://your-backend-api.com', // 替换为你的后端API端点
        onUserLoggedIn: (User user) {
          // 用户登录后的回调
          print('User logged in: ${user.username}');
        },
        onUserLoggedOut: () {
          // 用户登出后的回调
          print('User logged out');
        },
      ),
    );
  }
}

3. 自定义和扩展

虽然social_app_template可能提供了一个基础的社交应用框架,但你可能需要自定义和扩展其功能。例如,你可能想添加自定义的用户界面组件或处理特定的业务逻辑。

假设SocialApp小部件允许你通过插槽(slots)或构建器(builders)来自定义某些部分,你可以这样做:

home: SocialApp(
  apiKey: 'your_api_key',
  endpoint: 'https://your-backend-api.com',
  onUserLoggedIn: (User user) {
    print('User logged in: ${user.username}');
  },
  onUserLoggedOut: () {
    print('User logged out');
  },
  customFeedBuilder: (BuildContext context, List<Post> posts) {
    return ListView.builder(
      itemCount: posts.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(posts[index].title),
          subtitle: Text(posts[index].content),
        );
      },
    );
  },
),

在上面的代码中,customFeedBuilder是一个假设的参数,它允许你自定义信息流(feed)的显示方式。

4. 运行应用

最后,运行你的Flutter应用:

flutter run

注意

  • 由于social_app_template是一个假设的插件,上述代码中的类名、方法名和参数可能并不真实存在。你需要参考实际的插件文档来了解如何正确使用它。
  • 在实际开发中,处理用户认证、数据持久化和后端交互时,务必遵循最佳实践和安全性准则。
  • 考虑使用Flutter的BLoC模式、Provider状态管理等架构来组织你的代码,以保持应用的可维护性和可扩展性。
回到顶部