Merge pull request #17 from Nealyang/master

add collection and judge mounted
This commit is contained in:
Nealyang
2019-01-10 19:47:41 +08:00
committed by GitHub
13 changed files with 247 additions and 118 deletions

View File

@ -5,7 +5,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.2' classpath 'com.android.tools.build:gradle:3.2.0'
} }
} }

View File

@ -1,6 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017 #Thu Jan 10 15:37:36 CST 2019
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip

BIN
assets/images/nothing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import '../routers/application.dart';
class ListViewItem extends StatelessWidget {
final String itemUrl;
final String itemTitle;
final String data;
const ListViewItem({Key key, this.itemUrl, this.itemTitle, this.data})
: super(key: key);
void _launchURL(String url, BuildContext context) async {
if (url.contains("https") || url.contains("http")) {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
} else {
Application.router.navigateTo(context, "${url}");
}
}
@override
Widget build(BuildContext context) {
return Card(
color: Colors.white,
elevation: 4.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: ListTile(
onTap: () {
_launchURL(itemUrl, context);
},
title: Padding(
child: Text(
itemTitle,
style: TextStyle(color: Colors.black, fontSize: 15.0),
),
padding: EdgeInsets.only(top: 10.0),
),
subtitle: Row(
children: <Widget>[
Padding(
child: Text(data,
style: TextStyle(color: Colors.black54, fontSize: 10.0)),
padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
)
],
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
),
);
}
}

View File

@ -1,55 +0,0 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class ListViewItem extends StatelessWidget {
final String itemUrl;
final String itemTitle;
final String data;
const ListViewItem({Key key, this.itemUrl, this.itemTitle, this.data})
: super(key: key);
void _launchURL(String url,BuildContext context) async {
if (url.contains("https") || url.contains("http")) {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}else{
Navigator.of(context).pushNamed(url);
}
}
@override
Widget build(BuildContext context) {
return Card(
color: Colors.white,
elevation: 4.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: ListTile(
onTap: () {
_launchURL(itemUrl,context);
},
title: Padding(
child: Text(
itemTitle,
style: TextStyle(color: Colors.black, fontSize: 15.0),
),
padding: EdgeInsets.only(top: 10.0),
),
subtitle: Row(
children: <Widget>[
Padding(
child: Text(data,
style: TextStyle(color: Colors.black54, fontSize: 10.0)),
padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
)
],
),
trailing: Icon(Icons.keyboard_arrow_right,
color: Colors.grey, size: 30.0)));
}
}

View File

@ -14,18 +14,21 @@ class Provider {
//Get a location using getDatabasesPath //Get a location using getDatabasesPath
String databasesPath = await getDatabasesPath(); String databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'flutter.db'); String path = join(databasesPath, 'flutter.db');
List<Map> list; List<Map> tables;
// try { try {
// db = await openDatabase(path, readOnly: true); db = await openDatabase(path);
tables = await db
.rawQuery('SELECT name FROM sqlite_master WHERE type = "table"');
print('${tables.length} 7891');
} catch (e) {
print("Error $e");
}
// } catch (e) { if (tables.length < 3) {
// print("Error $e");
// }
if (db == null) {
// Delete the database // Delete the database
await deleteDatabase(path); await deleteDatabase(path);
// 关闭上面打开的db否则无法执行open
db.close();
ByteData data = await rootBundle.load(join("assets", "app.db")); ByteData data = await rootBundle.load(join("assets", "app.db"));
List<int> bytes = List<int> bytes =
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);

View File

@ -10,6 +10,8 @@ import '../components/markdown.dart';
import '../model/collection.dart'; import '../model/collection.dart';
import '../widgets/index.dart'; import '../widgets/index.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import '../event/event-bus.dart';
import '../event/event-model.dart';
class WidgetDemo extends StatefulWidget { class WidgetDemo extends StatefulWidget {
final List<dynamic> contentList; final List<dynamic> contentList;
@ -84,9 +86,11 @@ class _WidgetDemoState extends State<WidgetDemo> {
_router = item.routerName; _router = item.routerName;
} }
}); });
setState(() { if(this.mounted){
setState(() {
_hasCollected = list.length > 0; _hasCollected = list.length > 0;
}); });
}
}); });
} }
@ -100,6 +104,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
_hasCollected = false; _hasCollected = false;
}); });
showInSnackBar('已取消收藏'); showInSnackBar('已取消收藏');
ApplicationEvent.event.fire(CollectionEvent(widget.title,true));
return; return;
} }
print('删除错误'); print('删除错误');
@ -113,6 +118,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
setState(() { setState(() {
_hasCollected = true; _hasCollected = true;
}); });
ApplicationEvent.event.fire(CollectionEvent(widget.title,false));
showInSnackBar('收藏成功'); showInSnackBar('收藏成功');
} }
}); });
@ -167,6 +173,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: _getCollection, onPressed: _getCollection,
mini: true,
tooltip: '收藏', tooltip: '收藏',
child: Icon( child: Icon(
Icons.star, Icons.star,

View File

@ -9,12 +9,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:math'; import 'dart:math';
class ListRefresh extends StatefulWidget { class ListRefresh extends StatefulWidget {
final renderItem; final renderItem;
final requestApi; final requestApi;
const ListRefresh([this.requestApi,this.renderItem]) : super(); const ListRefresh([this.requestApi, this.renderItem]) : super();
@override @override
State<StatefulWidget> createState() => listRefresh(); State<StatefulWidget> createState() => listRefresh();
@ -34,7 +33,8 @@ class listRefresh extends State<ListRefresh> {
_getMoreData(); _getMoreData();
_scrollController.addListener(() { _scrollController.addListener(() {
// 如果下拉的当前位置到scroll的最下面 // 如果下拉的当前位置到scroll的最下面
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMoreData(); _getMoreData();
} }
}); });
@ -43,7 +43,7 @@ class listRefresh extends State<ListRefresh> {
/* /*
* 回弹效果 * 回弹效果
* */ * */
backElasticEffect(){ backElasticEffect() {
// double edge = 50.0; // double edge = 50.0;
// double offsetFromBottom = _scrollController.position.maxScrollExtent - _scrollController.position.pixels; // double offsetFromBottom = _scrollController.position.maxScrollExtent - _scrollController.position.pixels;
// if (offsetFromBottom < edge) { // 添加一个动画没有更多数据的时候 ListView 向下移动覆盖正在加载更多数据的标志 // if (offsetFromBottom < edge) { // 添加一个动画没有更多数据的时候 ListView 向下移动覆盖正在加载更多数据的标志
@ -58,18 +58,22 @@ class listRefresh extends State<ListRefresh> {
* list探底执行的具体事件 * list探底执行的具体事件
* */ * */
Future _getMoreData() async { Future _getMoreData() async {
if (!isLoading && _hasMore) { // 如果上一次异步请求数据完成 同时有数据可以加载 if (!isLoading && _hasMore) {
// 如果上一次异步请求数据完成 同时有数据可以加载
setState(() => isLoading = true); setState(() => isLoading = true);
//if(_hasMore){ // 还有数据可以拉新 //if(_hasMore){ // 还有数据可以拉新
List newEntries = await mokeHttpRequest(); List newEntries = await mokeHttpRequest();
//if (newEntries.isEmpty) { //if (newEntries.isEmpty) {
_hasMore = (_pageIndex <= _pageTotal); _hasMore = (_pageIndex <= _pageTotal);
setState(() { if (this.mounted) {
items.addAll(newEntries); setState(() {
isLoading = false; items.addAll(newEntries);
}); isLoading = false;
});
}
backElasticEffect(); backElasticEffect();
}else if (!isLoading && !_hasMore){ // 这样判断,减少以后的绘制 } else if (!isLoading && !_hasMore) {
// 这样判断,减少以后的绘制
_pageIndex = 0; _pageIndex = 0;
backElasticEffect(); backElasticEffect();
} }
@ -79,12 +83,12 @@ class listRefresh extends State<ListRefresh> {
* 伪装吐出新数据 * 伪装吐出新数据
* */ * */
Future<List> mokeHttpRequest() async { Future<List> mokeHttpRequest() async {
if(widget.requestApi is Function){ if (widget.requestApi is Function) {
final listObj = await widget.requestApi({'pageIndex':_pageIndex}); final listObj = await widget.requestApi({'pageIndex': _pageIndex});
_pageIndex = listObj['pageIndex']; _pageIndex = listObj['pageIndex'];
_pageTotal = listObj['total']; _pageTotal = listObj['total'];
return listObj['list']; return listObj['list'];
}else { } else {
return Future.delayed(Duration(seconds: 2), () { return Future.delayed(Duration(seconds: 2), () {
return []; return [];
}); });
@ -97,20 +101,23 @@ class listRefresh extends State<ListRefresh> {
* */ * */
Future<Null> _handleRefresh() async { Future<Null> _handleRefresh() async {
List newEntries = await mokeHttpRequest(); List newEntries = await mokeHttpRequest();
setState(() { if (this.mounted) {
items.clear(); setState(() {
items.addAll(newEntries); items.clear();
isLoading = false; items.addAll(newEntries);
_hasMore = true; isLoading = false;
return null; _hasMore = true;
}); return null;
});
}
} }
/* /*
* 加载中的提示 * 加载中的提示
* */ * */
Widget _buildLoadText() { Widget _buildLoadText() {
return Container(child: Padding( return Container(
child: Padding(
padding: const EdgeInsets.all(18.0), padding: const EdgeInsets.all(18.0),
child: Center( child: Center(
child: Text("数据没有更多了!!!"), child: Text("数据没有更多了!!!"),
@ -122,23 +129,28 @@ class listRefresh extends State<ListRefresh> {
* 上提加载loading的widget,如果数据到达极限,显示没有更多 * 上提加载loading的widget,如果数据到达极限,显示没有更多
* */ * */
Widget _buildProgressIndicator() { Widget _buildProgressIndicator() {
if(_hasMore){ if (_hasMore) {
return new Padding( return new Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: new Center( child: new Center(
child:Column( child: Column(
children: <Widget>[ children: <Widget>[
new Opacity( new Opacity(
opacity: isLoading ? 1.0 : 0.0, opacity: isLoading ? 1.0 : 0.0,
child: new CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.blue)), child: new CircularProgressIndicator(
), valueColor: AlwaysStoppedAnimation(Colors.blue)),
SizedBox(height:20.0), ),
Text('稍等片刻更精彩...',style: TextStyle(fontSize: 14.0),) SizedBox(height: 20.0),
],) Text(
//child: '稍等片刻更精彩...',
), style: TextStyle(fontSize: 14.0),
)
],
)
//child:
),
); );
}else { } else {
return _buildLoadText(); return _buildLoadText();
} }
} }
@ -152,11 +164,11 @@ class listRefresh extends State<ListRefresh> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new RefreshIndicator( return new RefreshIndicator(
child:ListView.builder( child: ListView.builder(
itemCount: items.length + 1, itemCount: items.length + 1,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if(index == 0 && index != items.length){ if (index == 0 && index != items.length) {
return Container(height:0); return Container(height: 0);
} }
if (index == items.length) { if (index == items.length) {
//return _buildLoadText(); //return _buildLoadText();
@ -165,7 +177,7 @@ class listRefresh extends State<ListRefresh> {
//print('itemsitemsitemsitems:${items[index].title}'); //print('itemsitemsitemsitems:${items[index].title}');
//return ListTile(title: Text("Index${index}:${items[index].title}")); //return ListTile(title: Text("Index${index}:${items[index].title}"));
if (widget.renderItem is Function) { if (widget.renderItem is Function) {
return widget.renderItem(index,items[index]); return widget.renderItem(index, items[index]);
} }
//return makeCard(index,items[index]); //return makeCard(index,items[index]);
} }
@ -175,4 +187,4 @@ class listRefresh extends State<ListRefresh> {
onRefresh: _handleRefresh, onRefresh: _handleRefresh,
); );
} }
} }

5
lib/event/event-bus.dart Normal file
View File

@ -0,0 +1,5 @@
import 'package:event_bus/event_bus.dart';
class ApplicationEvent{
static EventBus event;
}

View File

@ -0,0 +1,6 @@
class CollectionEvent{
final String widgetName;
final bool isRemove;
// token uid...
CollectionEvent(this.widgetName,this.isRemove);
}

View File

@ -14,6 +14,8 @@ import 'model/widget.dart';
import './widgets/index.dart'; import './widgets/index.dart';
import 'package:flutter_rookie_book/components/SearchInput.dart'; import 'package:flutter_rookie_book/components/SearchInput.dart';
const int ThemeColor = 0xFFC91B3A; const int ThemeColor = 0xFFC91B3A;
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {

View File

@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_rookie_book/common/myListView.dart'; import 'package:flutter_rookie_book/common/list_view_item.dart';
//import 'package:flutter_rookie_book/components/CompList.dart'; //import 'package:flutter_rookie_book/components/CompList.dart';
import 'package:flutter_rookie_book/components/ListRefresh.dart' as listComp; import 'package:flutter_rookie_book/components/ListRefresh.dart' as listComp;
import 'package:flutter_rookie_book/components/Pagination.dart'; import 'package:flutter_rookie_book/components/Pagination.dart';

View File

@ -6,30 +6,123 @@
*/ */
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../model/collection.dart'; import '../model/collection.dart';
import '../routers/application.dart';
import '../event/event-bus.dart';
import '../event/event-model.dart';
import 'package:event_bus/event_bus.dart';
class CollectionPage extends StatefulWidget { class CollectionPage extends StatefulWidget {
_CollectionPageState createState() => _CollectionPageState(); _CollectionPageState createState() => _CollectionPageState();
} }
class _CollectionPageState extends State<CollectionPage> { class _CollectionPageState extends State<CollectionPage> {
_CollectionPageState() {
final eventBus = new EventBus();
ApplicationEvent.event = eventBus;
}
CollectionControlModel _collectionControl = new CollectionControlModel(); CollectionControlModel _collectionControl = new CollectionControlModel();
List<Collection> _collectionList = []; List<Collection> _collectionList;
ScrollController _scrollController = new ScrollController();
@override @override
void initState() { void initState() {
// TODO: implement initState
super.initState(); super.initState();
_getList();
ApplicationEvent.event.on<CollectionEvent>().listen((event) {
_getList();
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _getList() {
_collectionList = [];
_collectionControl.getAllCollection().then((resultList) {
resultList.forEach((item) {
_collectionList.add(item);
});
if (this.mounted) {
setState(() {
_collectionList = _collectionList;
});
}
});
}
Widget _renderList(context, index) {
if (index == 0) {
return Container(
height: 40.0,
padding: const EdgeInsets.only(left: 10.0),
child: Row(
children: <Widget>[
Icon(
Icons.warning,
size: 22.0,
),
SizedBox(
width: 5.0,
),
Text('模拟器重新运行会丢失收藏'),
],
),
);
}
return Container(
padding: const EdgeInsets.all(10.0),
margin: const EdgeInsets.only(bottom: 7.0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
new BoxShadow(
color: const Color(0xFFd0d0d0),
blurRadius: 1.0,
spreadRadius: 2.0,
offset: Offset(3.0, 2.0),
),
],
),
child: ListTile(
title: Text(
_collectionList[index - 1].name,
style: TextStyle(fontSize: 17.0),
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
onTap: () {
Application.router
.navigateTo(context, "${_collectionList[index - 1].router}");
},
),
);
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_collectionControl.getAllCollection().then((resultList) { print(_collectionList);
_collectionList = resultList; if (_collectionList.length == 0) {
_collectionList.forEach((item){ return ListView(
print(item.toMap()); children: <Widget>[
}); Column(
}); children: <Widget>[
return Container( Image.asset(
child: Text('敬请期待'), 'assets/images/nothing.png',
fit: BoxFit.contain,
width: MediaQuery.of(context).size.width / 2,
),
Text('暂无收藏,赶紧去收藏一个吧!'),
],
),
],
);
}
return ListView.builder(
itemBuilder: _renderList,
itemCount: _collectionList.length + 1,
controller: _scrollController,
); );
} }
} }