前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >抖音的强大对手来了,用Flutter手撸一个抖音国际版,看看有多炫

抖音的强大对手来了,用Flutter手撸一个抖音国际版,看看有多炫

作者头像
肉眼品世界
发布2022-03-29 14:26:33
1K0
发布2022-03-29 14:26:33
举报
文章被收录于专栏:肉眼品世界

前言

由于中间几个月项目天天加班,导致没没时间更新,最近一段时间对前端进行了重构,加了很多页面,如登录、注册、关注、个人中心等,目前写这个纯属业余个人爱好,所以断断续续的继续在做......

前端地址:https://www.pgyer.com/dtok 后端服务器地址:http://47.95.209.198:8181/

注释:由于本人的apple id无法打包ios、所以暂时只打包的android版本,ios版本正在解决账号问题

效果如下:

架构更新

之前技术采用flutter做的前端,后端api则对接的是抖音官方api,由于抖音的官方api更新频繁,导致经常播放不了,所以索性自己来写服务器后端api,那么后端api采用了那些技术咧

  • springcloud 主要是后台控制面板 演示地址:http://47.95.209.198:8181/login
  • elasticsearch 主要对视频数据离线查询
  • ipfs 用于分布式节点存储短视频
  • ethereum 用户激励用户存储短视频、毕竟买服务器存花费够大的

界面更新

  • 支持国家化,多语言切换
  • ipfs上传、下载文件
  • 登录页面
  • 注册页面
  • 上下轮播时优化播放效果
  • 点赞功能

其他功能还在继续完善,各位喜欢的话欢迎点个star 前端项目地址:https://github.com/telsacoin/telsavideo 后端需要的话请留下邮箱

本期最大的优化就是国际化,flutter国家化按以下步骤

在pubspec.yaml文件加上

代码语言:javascript
复制
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: ^0.17.0 # Add this line
  ffi: ^1.1.2

在底部的flutter设置里添加:

代码语言:javascript
复制
# The following section is specific to Flutter.
flutter:
  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true
  generate: true # Add this line

新建多语言包

在lib目录新建子目录l10n 里面添加app_zh.arb文件 内容如下:

代码语言:javascript
复制
{
    "home_top_foryou":"推荐",
    "home_top_following":"关注",
    "home_share":"分享",
    "home_buttom_title":"首页",
    "home_buttom_discover":"发现",
    "home_buttom_notification":"通知",
    "home_buttom_persion":"我"
}

在main文件引用:

代码语言:javascript
复制
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

在build里加入多语言检测及支持的代码:

代码语言:javascript
复制
return MaterialApp(
    debugShowCheckedModeBanner: false,
    onGenerateTitle: (context) =>
        AppLocalizations.of(context)!.home_buttom_title,
    home: SplashScreen(),
    localeResolutionCallback: (
      Locale? locale,
      Iterable<Locale> supportedLocales,
    ) {
      return locale;
    },
    localizationsDelegates: AppLocalizations.localizationsDelegates,
    supportedLocales: AppLocalizations.supportedLocales,
    theme: ThemeData(
      textSelectionTheme: TextSelectionThemeData(
        cursorColor: Colors.white,
      ),
      splashColor: Colors.transparent,
      highlightColor: Colors.transparent,
      primarySwatch: Colors.red,
      primaryColor: Colors.black,
      indicatorColor: Colors.white,
      tabBarTheme: TabBarTheme(),
    ),
    /* initialRoute: '/',
   onGenerateRoute: RouteGenerator.generateRoute, */
    builder: (context, child) {
      return ScrollConfiguration(
        behavior: MyBehavior(),
        child: child!,
      );
    },
  );

然后在需要引用的位置加入:

代码语言:javascript
复制
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

调用的位置:

代码语言:javascript
复制
AppLocalizations.of(context)!.home_top_foryou

至此,国际化就完成了

另外本地针对播放模块进行了优化,将代码拆分到videoplayer.dart文件.一来是方便代码阅读,而来可以作为子组件使用,其他的代码写得太冗余也在继续拆开,独立出来,各位感兴趣的可以关注项目的进展。

采用FutureBuilder对界面请求数据异步处理,当加载完成后才播放,效果更佳

代码如下:

代码语言:javascript
复制
eturn FutureBuilder<DTok>(
    future: videos,
    builder: (context, snapshot) {
      print(snapshot.connectionState);
      if (snapshot.connectionState == ConnectionState.waiting) {
        return loading;
        // return Column(
        //   crossAxisAlignment: CrossAxisAlignment.center,
        //   mainAxisAlignment: MainAxisAlignment.center,
        //   children: [
        //     loading,
        //     Visibility(
        //       visible: snapshot.hasData,
        //       child: PageView.builder(
        //           controller: foryouController,
        //           onPageChanged: (index) {
        //             //when the video is changing, release the previous video instance.
        //             //disposeVideo();
        //             setState(() {});
        //           },
        //           scrollDirection: Axis.vertical,
        //           itemCount: snapshot.data!.itemList!.length,
        //           itemBuilder: (context, index) {
        //             var item = snapshot.data!.itemList![index];
        //             return Videoplayer(
        //               item: item,
        //               width: MediaQuery.of(context).size.width,
        //               heigth: MediaQuery.of(context).size.height,
        //             );
        //           }),
        //     )
        //   ],
        // );
      } else if (snapshot.connectionState == ConnectionState.done) {
        if (snapshot.hasError) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('Error, Please restart your app agagin')
            ],
          );
        } else if (snapshot.hasData) {
          try {
            return PageView.builder(
                controller: foryouController,
                onPageChanged: (index) {
                  //when the video is changing, release the previous video instance.
                  //disposeVideo();
                  //setState(() {});
                },
                scrollDirection: Axis.vertical,
                itemCount: snapshot.data!.itemList!.length,
                itemBuilder: (context, index) {
                  var item = snapshot.data!.itemList![index];
                  return Videoplayer(
                    item: item,
                    width: MediaQuery.of(context).size.width,
                    heigth: MediaQuery.of(context).size.height,
                  );
                });
          } catch (e) {
            return Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              color: Colors.black,
              child: Center(
                  child: Text(
                'Error, Please restart your app again.',
                style: TextStyle(color: Colors.white),
              )),
            );
          }
        } else {
          // empty data
          return loading;
        }
      } else {
        return Text('State: ${snapshot.connectionState}');
      }
    });

这里可以看到当snapshot.connectionState == ConnectionState.waiting的时候请求的数据正在加载中,则显示加载的图标loading

当snapshot.connectionState == ConnectionState.done 时,此时数据已经加载完毕,但是加载完毕有可能也没有数据,所以需要判断不同的情况

当加载出现异常情况则显示异常的widget

代码语言:javascript
复制
if (snapshot.hasError) {
      return Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text('Error, Please restart your app agagin')
        ],
      );
    } 

当if (snapshot.hasData)则说明有返回值,但是这个返回值不一定就是我们需要的数据,所以还需要try catch一下,保证呈现给用户的界面是正常的

代码语言:javascript
复制
try {
      return PageView.builder(
          controller: foryouController,
          onPageChanged: (index) {
            //when the video is changing, release the previous video instance.
            //disposeVideo();
            //setState(() {});
          },
          scrollDirection: Axis.vertical,
          itemCount: snapshot.data!.itemList!.length,
          itemBuilder: (context, index) {
            var item = snapshot.data!.itemList![index];
            return Videoplayer(
              item: item,
              width: MediaQuery.of(context).size.width,
              heigth: MediaQuery.of(context).size.height,
            );
          });
    } catch (e) {
      return Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        color: Colors.black,
        child: Center(
            child: Text(
          'Error, Please restart your app again.',
          style: TextStyle(color: Colors.white),
        )),
      );
    }
  } 

其他情况则返回加载状态,因为没有数据返回

另外加载videoplay的时候把width、heigth传入到下一个控件,这样好计算界面呈现的宽度与高度

代码语言:javascript
复制
return Videoplayer(
        item: item,
        width: MediaQuery.of(context).size.width,
        heigth: MediaQuery.of(context).size.height,
      );

结语

请继续关注本博客,其他页面持续更新完成,源码地址:telsavideo, 欢迎fork和star,谢谢!!!

再次奉上演示地址: 前端地址:https://www.pgyer.com/dtok 后端服务器地址:http://47.95.209.198:8181/

作者:风清扬 No.1 出处:http://www.cnblogs.com/fengqingyangNo1

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 肉眼品世界 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 架构更新
  • 界面更新
  • 本期最大的优化就是国际化,flutter国家化按以下步骤
  • 新建多语言包
  • 至此,国际化就完成了
  • 采用FutureBuilder对界面请求数据异步处理,当加载完成后才播放,效果更佳
  • 结语
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档