美文网首页
Flutter学习之豆瓣电影

Flutter学习之豆瓣电影

作者: loongod | 来源:发表于2019-03-08 14:32 被阅读0次
运行效果图.gif

0. 主要实现功能

  • 网络请求
  • Json数据转Model
  • TabBar切换不重新init页面
  • 无限列表
  • 下拉刷新、上拉加载

1. 页面布局

页面布局使用的是PageView + BottomNavigationBar。
用此布局,然后再PageView的Widget里采用AutomaticKeepAliveClientMixin,即可实现切换Tab保存Widget状态。

class CurrentMovieState extends State<CurrentMovie> with AutomaticKeepAliveClientMixin<CurrentMovie> {

  @override
  bool get wantKeepAlive => true;
  ...
}

2. 网络请求和数据解析

网络请求用的是dio


  // 网络请求
  Future getDouBanCurrentMovie() async {
    try {
      Response response = await Dio()
          .get("https://api.douban.com/v2/movie/in_theaters?count=20");
      print(response.statusCode); // 此处应该判断状态码
      final jsonResponse = json.decode(response.toString());
      print(jsonResponse);
      DouBanMovieData tempDoubanModel = new DouBanMovieData.fromJson(jsonResponse);
      print(tempDoubanModel.movies[0].image);

      setState(() {
        movies = tempDoubanModel.movies;
      });
    }catch (e) {
      print(e);
    }
  }

因为只有一种数据模型,我只新建了一个model文件,douban_data.dart里面存放了数据Model。

/// 豆瓣列表Data Model
class DouBanMovieData {
  String title;
//  double count; // 每页最多数量
//  double total; // 当前页条目数
  List<Movie> movies; // 电影列表

  DouBanMovieData({
    this.title,
//    this.count,
//    this.total,
    this.movies,
  });

  factory DouBanMovieData.fromJson(Map<String, dynamic> json) {
    var list = json['subjects'] as List;
    List<Movie> movieList = list.map((i) => Movie.fromJson(i)).toList();

    return DouBanMovieData(
        title: json['title'],
//        count: json['count'],
//        total: json['total'],
        movies: movieList
    );
  }
}

/// 豆瓣电影Model
class Movie {
  num rating; // 电影评分
  int collectCount; // 收藏数 | 观看人数
  String title; // 电影名
  List<Person> casts; // 演员表
  String originalTitle; // 原始名
  String subtype; // 类型
  String year; // 电影年份
  String image; // 电影海报
  List<String> genres; // 电影类型
  List<Person> directors; // 电影导演表
  String alt; // 电影简介地址
  String id;

  Movie({
    this.rating,
    this.collectCount,
    this.title,
    this.casts,
    this.originalTitle,
    this.subtype,
    this.year,
    this.image,
    this.genres,
    this.directors,
    this.alt,
    this.id
  });

  factory Movie.fromJson(Map<String, dynamic> mJson) {
    var gList = mJson['genres'];
    List<String> genresList = new List<String>.from(gList);

    var cList = mJson['casts'] as List;
    List<Person> castsList = cList.map((i) => Person.fromJson(i)).toList();

    var dList = mJson['directors'] as List;
    List<Person> directorList = dList.map((i) => Person.fromJson(i)).toList();

    num average = mJson['rating']['average'];


    return Movie(
        rating: average,
        collectCount: mJson['collect_count'],
        title: mJson['title'],
        casts: castsList,
        originalTitle: mJson['original_title'],
        subtype: mJson['subtype'],
        year: mJson['year'],
        image: mJson['images']['medium'],
        genres: genresList,
        directors: directorList,
        alt: mJson['alt'],
        id: mJson['id']
    );
  }
}
 
class Person {
  String alt; // 简介
  String avatar; // 头像
  String name; // 名字
  String id;

  Person({
    this.alt,
    this.avatar,
    this.name,
    this.id,
  });

  factory Person.fromJson(Map<String, dynamic> pJson) {
    var avatar = '';
    if (pJson['avatars'] != null) {
      avatar = pJson['avatars']['medium'];
    }

    return Person(
        alt: pJson['alt'],
        avatar: avatar,
        name: pJson['name'],
        id: pJson['id']
    );
  }
}

解析的时候有点小插曲,在解析 Movie 时,有个属性 rating; //电影评分。我先开始设的属性是double类型,在解析正在热映列表的时候,没出现问题,但是到了解析即将上映电影列表的时候,就报错,一直报 a int type not a subtype a double。因为有好几个double类型的属性,我也不知道哪一个。我看了下数据,发现在即将上映的电影中有的评分是0,然后就会被认为 int

所以遇到这种不确定的数字数据类型,可以使用 num 来解析。

如果是使用 num 声明的变量,可以随意的转换类型,但是如果是使用了 int 或者 double 明确的声明,那么就不能转换了。

4. 下拉刷新、下拉加载

下拉刷新动画使用的是liquid_pull_to_refresh。集成很简单可参考文档。

上拉加载没找到好的库😳。然后搜资料,都是根据监听List的controller的滑动位置,来加载更多。

  @override
  void initState() {
    super.initState();
    getDouBanTopMovie();

    scrollController.addListener(() {
      if (scrollController.offset == scrollController.position.maxScrollExtent) {
        if (!isNoMore) {
          loadMore();
        }
      }
    });
  }

loadMore里设置动画属性和请求更多数据。


完整代码已上传github

end. 参考

在Flutter中解析复杂的Json

相关文章

网友评论

      本文标题:Flutter学习之豆瓣电影

      本文链接:https://www.haomeiwen.com/subject/nublpqtx.html