美文网首页
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