我正在尝试使用 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;
}
块飞镖
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 ,这很明显,因为我正在创建一个具有不同参数的新块。