简介
最近花了两天时间研究使用 Flutter 开发一个抖音国际版. 个人感觉使用 Flutter 开发 App 快得不要不要的额. 两天就基本可以开发个大概出来. 最主要是热重载, 太方便实时调整 UI 布局了. 相应速度极快. 如下图:
主要项目架构
详细说明一下, 开发主要在 lib 文件夹
pubspec.YAML 是配置插件的位置, 如 http: ^0.12.0+4, 类似依赖组件.
common 文件夹存放的是重写的网络组件, 以及图标组件 icons.dart
config 文件夹存放的 API.dart,wei 调用的 API 配置文件
models 文件存放的实体层
screen 文件夹存放的页面 view 层
tabs 存放的底部切换文件夹层
widgets 存放的组件, 包含视频播放组件 player.dart 以及左右等描述组件
功能介绍
主要的依赖组件, 请使用国内镜像下载, 切记切记!!!!
- flutter:
- sdk: flutter
- flutter_svg: ^0.17.4
- # The following adds the Cupertino Icons font to your application.
- # Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^0.1.3
- cached_network_image: ^2.2.0
- json_annotation: ^3.0.1
- font_awesome_flutter: ^8.8.1
- http: ^0.12.0+4
- provider: ^4.0.4
- avatar_glow: any
- getflutter: ^1.0.11
- flutter_money_formatter: ^0.8.3
- video_player: ^0.10.8+1
- dio: ^3.0.9
- dio_cookie_manager: ^1.0.0
包含字体文件, 主要为抖音自带的字体文件
- import 'package:flutter/widgets.dart';
- class DouyinIcons {
- DouyinIcons._();
- static const _kFontFam = 'DouyinIcons';
- static const IconData chat_bubble =
- const IconData(0xe808, fontFamily: _kFontFam);
- static const IconData create = const IconData(0xe809, fontFamily: _kFontFam);
- static const IconData heart = const IconData(0xe80a, fontFamily: _kFontFam);
- static const IconData home = const IconData(0xe80b, fontFamily: _kFontFam);
- static const IconData messages =
- const IconData(0xe80c, fontFamily: _kFontFam);
- static const IconData profile = const IconData(0xe80d, fontFamily: _kFontFam);
- static const IconData reply = const IconData(0xe80e, fontFamily: _kFontFam);
- static const IconData search = const IconData(0xe80f, fontFamily: _kFontFam);
- }
此次采用 Flutter 开发安卓, iOS 等 App 确实方便, 主要为将 tiktok 的数据使用 http 下载下来.
- import 'package:http/http.dart' as http;
- class RequestController {
- static String host = "https://www.tiktok.com/";
- String url = host +
- "/share/item/list?secUid=&id=&type=5&count=30&minCursor=0&maxCursor=0&shareUid=&lang=en&_signature=pKb.ogAgEB9ImoSQahoqJKSm.rAAPox";
- Future<String> getCookie() async {
- try {
- var response = await http.get(host + "/share/item/");
- return response.headers["set-cookie"];
- } catch (e) {
- return "error";
- }
- }
Model 层
主要为实体层, 解析 JSON 后绑定数据以及传递数据
- class Tiktok {
- int statueCode;
- Body body;
- Object errMsg;
- Tiktok({this.statueCode, this.body, this.errMsg});
- Tiktok.fromJson(Map<String, dynamic> JSON) {
- statueCode = JSON['statusCode'];
- body = JSON['body'] != null ? new Body.fromJson(JSON['body']) : null;
- errMsg = JSON['errMsg'];
- }
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> data = new Map<String, dynamic>();
- data['statusCode'] = this.statueCode;
- if (this.body != null) {
- data['body'] = this.body.toJson();
- }
- data['errMsg'] = this.errMsg;
- return data;
- }
- }
视图层
另外屏幕层主要包含三个, homescreen,trendingscreen, 以及显示 videoscreen
- import 'package:flutter/material.dart';
- import 'package:flutter_app/Screens/trendingScreen.dart';
- import 'package:flutter_app/widgets/bottom_toolbar.dart';
- class Home extends StatefulWidget {
- @override
- HomeState createState() => HomeState();
- }
- class HomeState extends State<Home> {
- int currentIndex = 0;
- PageController pageController;
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: PageView(
- controller: pageController,
- children: <Widget>[
- Trending(),
- ],
- onPageChanged: (int index) {
- setState(() {
- currentIndex = index;
- });
- },
- ),
- bottomNavigationBar: bottomItems(currentIndex, pageController),
- );
- }
- }
Tending 层, 主要包含读取抖音的 API, 将 API 转化成实体对象, 绑定数据到 videoscreen 页面
- import 'dart:convert';
- import 'package:flutter/material.dart';
- import 'package:flutter/cupertino.dart';
- import 'package:getflutter/getflutter.dart';
- import 'package:flutter_app/config/api.dart';
- import 'package:flutter_app/models/Tiktok.dart';
- import 'package:http/http.dart' as http;
- import 'package:flutter_app/Screens/videoScreen.dart';
- class Trending extends StatefulWidget {
- _TrendingState createState() => _TrendingState();
- }
- class _TrendingState extends State<Trending> {
- PageController pageController;
- BuildContext context;
- RequestController API = RequestController();
- List<Widget> videos = [];
- getTrending() async {
- var cookies = await API.getCookie();
- API.setCookie(cookies);
- try {
- var response = await http.get(
- API.url,
- headers: API.headers,
- );
- Tiktok tiktok = Tiktok.fromJson(jsonDecode(response.body));
- tiktok.body.itemListData.forEach(
- (item) {
- setState(() {
- videos.add(VideoItem(data: item));
- });
- },
- );
- } catch (ex) {
- SimpleDialog(
- title: Text('Hot videos list is empty'),
- );
- print(ex);
- }
- }
- @override
- void initState() {
- super.initState();
- getTrending();
- }
- @override
- Widget build(BuildContext context) {
- context = context;
- return PageView(
- scrollDirection: Axis.vertical,
- controller: pageController,
- children: videos.length == 0
- ? <Widget>[
- Container(
- color: Colors.black,
- child: Center(
- child: GFLoader(
- type: GFLoaderType.circle,
- loaderColorOne: Colors.blueAccent,
- loaderColorTwo: Colors.white,
- loaderColorThree: Colors.pink,
- ),
- ),
- )
- ]
- : videos,
- );
- }
- }
VideoScreen 主要为绑定数据. 展示抖音的视频
- import 'package:flutter/material.dart';
- import 'package:flutter_app/models/Tiktok.dart';
- import 'package:flutter_app/widgets/video_description.dart';
- import 'package:flutter_app/widgets/actions_toolbar.dart';
- import 'package:flutter_app/widgets/player.dart';
- class VideoItem extends StatelessWidget {
- final ItemListData data;
- const VideoItem({@required this.data});
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: Stack(
- children: <Widget>[
- DouyinVideoPlayer(
- url: data.itemInfos.video.urls[0],
- ),
- title(),
- VideoDescription(
- description: data.itemInfos.text,
- musicName: data.musicInfos.musicName,
- authorName: data.musicInfos.authorName,
- userName: data.authorInfos.uniqueId,
- ),
- ActionsToolbar(
- comments: data.itemInfos.commentCount.toString(),
- userImg: data.authorInfos.covers[0],
- favorite: data.itemInfos.diggCount,
- coverImg: data.musicInfos.covers[0],
- ),
- ],
- ),
- );
- }
- Widget title() => Align(
- alignment: Alignment.topCenter,
- child: Padding(
- padding: EdgeInsets.symmetric(vertical: 28.0),
- child: Text(
- "Trending | For You",
- style: TextStyle(color: Colors.white, fontSize: 19.0),
- ),
- ),
- );
- }
此次开发主要时间用在搭建 Flutter 环境上, 切记使用国内镜像, 另外调式需要配合代理即可.
其他待完成的包含底部的导航页面, 打算花两天时间把剩余的完成.
各位感兴趣的可以到我的 GitHub 上点一下 star. 留言可以教你们开发以及搭建 dart 环境. 地址: https://github.com/WangCharlie/douyin
感兴趣的各位留言哈.
来源: https://www.cnblogs.com/fengqingyangNo1/p/12927538.html