如何以颤动块模式实现分页

时间:2019-04-07 08:11:48

标签: pagination flutter bloc built-value

我正在尝试使用bloc模式在分页中实现分页。我想要的是list_view到达末尾时使用新内容更新当前的list_view,但是它正在做的是使用新内容创建新的list_view

Built_valueModel.dart


abstract class Verces implements Built<Verces, VercesBuilder> {
  static Serializer<Verces> get serializer => _$vercesSerializer;

  BuiltList<Madni> get verses;

  Meta get meta;

  Verces._();

  factory Verces([updates(VercesBuilder b)]) = _$Verces;
}

abstract class Madni implements Built<Madni, MadniBuilder> {
  static Serializer<Madni> get serializer => _$madniSerializer;

  int get id; //1,
  int get verse_number; //: 1,
  int get chapter_id; //: 1,
  String get verse_key; // "1:1",
  String get text_madani; //: "بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ",
  String get text_indopak; //: "بِسۡمِ اللهِ الرَّحۡمٰنِ الرَّحِيۡمِ",
  String get text_simple; //: "بسم الله الرحمن الرحيم",
  int get juz_number; //: 1,
  int get hizb_number; //: 1,
  int get rub_number; // 1,
//  "sajdah": null,
//  "sajdah_number": null,
  int get page_number; // 1,

  BuiltList<Translations> get translations; //": [],

  Madni._();

  factory Madni([updates(MadniBuilder b)]) = _$Madni;
}

abstract class Translations
    implements Built<Translations, TranslationsBuilder> {
  static Serializer<Translations> get serializer => _$translationsSerializer;

  int get id; //: 104845,
  String get language_name; //: "english",
  String get text; //: "Alif Lam Mim.",
  String get resource_name; // "Shakir",
  int get resource_id; //: 21

  Translations._();

  factory Translations([updates(TranslationsBuilder b)]) = _$Translations;
}

abstract class Meta implements Built<Meta, MetaBuilder> {
  static Serializer<Meta> get serializer => _$metaSerializer;

  @nullable
  int get current_page; //": 1,
  @nullable
  int get next_page; //": 2,
  @nullable
  int get prev_page; //": null,
  @nullable
  int get total_pages; //": 6,
  @nullable
  int get total_count; //": 286

  Meta._();

  factory Meta([updates(MetaBuilder b)]) = _$Meta;
}

List<Madni> getmadni(String jsonStr) {
  final res = json.jsonDecode(jsonStr);
  Verces verces = standardSerializers.deserializeWith(Verces.serializer, res);
  //print(verces);
  return verces.verses.map((Madni mad) => mad).toList();
}

Meta getmeta(String jsonStr) {
  final res = json.jsonDecode(jsonStr);
  Verces verces = standardSerializers.deserializeWith(Verces.serializer, res);
  return verces.meta;
}

Bloc.dart

import 'dart:async';
import 'package:quran_app/src/chapters/model/model.dart';
import 'dart:collection';
import 'package:http/http.dart' as http;

class Verses_bloc {
  var _chap = <Madni>[];
  var _meta = Meta();

  HashMap<int, List<Madni>> _cashedChapters;

  // Verses bloc start
  final Verses_blocController = StreamController<List<Madni>>();

  StreamSink<List<Madni>> get _incontroller => Verses_blocController.sink;

  Stream<List<Madni>> get output_verses => Verses_blocController.stream;

  // Verses bloc End

  // Pages bloc start
  final pages_blocController = StreamController<Meta>();

  StreamSink<Meta> get _inpageController => pages_blocController.sink;

  Stream<Meta> get output_pages => pages_blocController.stream;

  // Pages bloc start

  int chap;
  int page;

  Verses_bloc(this.chap, this.page) {
    _cashedChapters = HashMap<int, List<Madni>>();

    update(this.chap, this.page);
  }

  // Future which will return value to UI when the data is fetched
  Future<void> update(int chap, int page) async {
     _chap = await getVerses(chap, page);

    _meta = await getPages();

    _incontroller.add(_chap);
    _inpageController.add(_meta);
  }

  // Get Verses Method Which will return pages with limit of 50 pages

  Future<List<Madni>> getVerses(int chap, int page) async {
    if (!_cashedChapters.containsKey(1)) {
      final storiesUrl =
          'http://staging.quran.com:3000/api/v3/chapters/${chap}/verses?recitation=1&translations=21&language=en&page=${page}&text_type=words';
      final storyRes = await http.get(Uri.parse(storiesUrl));

      if (storyRes.statusCode == 200) {
        _cashedChapters[1] = getmadni(storyRes.body);
      } else {
        throw Exception("Error");
      }
    }
    return _cashedChapters[1];
  }

  // Get Meta Quantities Method
  Future<Meta> getPages() async {
    final storiesUrl =
        'http://staging.quran.com:3000/api/v3/chapters/${chap}/verses?recitation=1&translations=21&language=en&page=2&limit=50&text_type=words';
    final storyRes = await http.get(Uri.parse(storiesUrl));

    if (storyRes.statusCode == 200) {
      return getmeta(storyRes.body);
    } else {
      throw Exception("Error");
    }
  }

  void dispose() {
    Verses_blocController.close();
  }
}

Main_UI.dart

import 'package:flutter/material.dart';
import 'package:quran_app/src/chapters/model/bloc/Verses_bloc.dart';
import 'package:quran_app/src/chapters/model/model.dart';

class Surah extends StatefulWidget {
  final String name;
  final int id;
  final int verses_count;

  const Surah({Key key, this.name, this.id, this.verses_count})
      : super(key: key);

  @override
  _SurahState createState() => _SurahState();
}

class _SurahState extends State<Surah> {
  var _bloc = Verses_bloc(0, 0);
  ScrollController _controller;
  int n = 1;

  _scrollListener() {
    if (_controller.offset >= _controller.position.maxScrollExtent &&
        !_controller.position.outOfRange) {
      setState(() {
        print("Reached end");

        // _bloc=Verses_bloc(widget.id,2);
        // This line is creating a new listview
        // instead of updating current listview

      });
    }
  }

  @override
  void initState() {
    _bloc = Verses_bloc(widget.id, n);
    _controller = ScrollController();
    _controller.addListener(_scrollListener);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.name),
      ),
      body: Container(
        child: StreamBuilder(
          stream: _bloc.output_verses,
          initialData: List<Madni>(),
          builder: (BuildContext context,
              AsyncSnapshot<List<Madni>> snapshot_Madni) {
            if (snapshot_Madni.connectionState == ConnectionState.waiting) {
              return Center(
                child: CircularProgressIndicator(),
              );
            } else if (snapshot_Madni.data.isEmpty) {
              return Center(
                child: Text("The End"),
              );
            } else {
              return ListView.builder(
                controller: _controller,
                padding: EdgeInsets.all(8.0),
                itemCount: n,
                addAutomaticKeepAlives: false,
                itemBuilder: (BuildContext context, index) {
                  return ListView(
                      physics: ClampingScrollPhysics(),
                      shrinkWrap: true,
                      children: snapshot_Madni.data.map(_buildList).toList());
                },
              );
            }
          },
        ),
      ),
    );
  }

  Widget _buildList(Madni e) {
    return ListView(
      children: e.translations
          .map<ListTile>((a) => ListTile(
                contentPadding: EdgeInsets.all(10),
                title: Text(
                  e.text_madani,
                  style: TextStyle(fontSize: 22.0),
                  textAlign: TextAlign.right,
                ),
                subtitle: Text(a.text),
              ))
          .toList(),
      physics: ClampingScrollPhysics(),
      shrinkWrap: true,
    );
  }

//  Get List Pages
  String getMeta() {
    StreamBuilder(
        stream: _bloc.output_pages,
        builder: (BuildContext context, AsyncSnapshot<Meta> snapshot) {
          return Center(
            child: Text('${snapshot.data.next_page}'),
          );
        });
  }


  @override
  void dispose() {
    super.dispose();
    _bloc.dispose();
    _controller.dispose();
  }
}

当list_view到达尽头而不是更新当前的list_view时,它会创建一个新的list_view,这很明显,因为我正在创建一个具有不同参数的新块。

1 个答案:

答案 0 :(得分:0)

我无法运行您的最小复制,但我之前创建了一个 sample app on Flutter demonstrating pagination with BLoC pattern。我在这里做的是逐渐显示数据,在列表底部滚动时加载更多数据。我遵循的 BLoC 模式基于此 guide