这篇文章主要讲解了如何使用Flutter中的mixin,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
mixin是什么
mixin应该怎么理解呢,对Java系出身的我来说,这是一个新概念,各类资料的介绍也没找到一个清晰的定义。从个人理解来看,可以把它想象为Kotlin中的接口(和Java的区别是可以带非抽象的属性和方法),而多个mixin可以相互覆盖以实现组合,提供了非常大的灵活性,也可以达到类似多重继承的效果。
页表页面
这是一个普通的展示数据,上拉加载更多数据的列表。
其中有一个类型为List<T>
的数据列表listData,有个page数据用于分页,isLoading用来判断是否正在加载数据,scrollController用于列表控制器
如果存在大量这种页面则可以用mixin来处理,不免大量重复的代码
import 'package:flutter/material.dart';
import 'package:flutter_app/app/model/ListViewJson.dart';
import 'package:flutter_app/app/shared/api/api.dart';
import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:flutter_app/app/shared/mixins/list_more_data_mixin.dart';
/// 列表页面
class RecommendView extends StatefulWidget {
@override
_RecommendViewState createState() => _RecommendViewState();
}
class _RecommendViewState
extends ListMoreDataBase<ListViewJsonData, RecommendView>
with ListMoreDataMixin<ListViewJsonData, RecommendView> {
@override
Future<List<ListViewJsonData>> getData() async {
String data = await DioUtils.postHttp(
"api/getOneLevel",
parameters: FormData.fromMap({
'page': page,
'limit': '10',
}),
);
ListViewJson _json = ListViewJson.fromJson(json.decode(data));
return _json.data;
}
@override
void initState() {
print('init widget');
super.initState();
}
@override
void dispose() {
print('dispose widget');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: Text('返回')),
body: Stack(
children: <Widget>[
NotificationListener<ScrollNotification>(
onNotification: onNotification,
child: ListView.builder(
controller: scrollController,
itemCount: listData.length,
itemBuilder: (BuildContext context, int index) =>
TeamListItem(listData[index]),
),
),
isLoading ? Center(child: CircularProgressIndicator()) : Container()
],
),
);
}
}
mixin
import 'package:flutter/material.dart';
abstract class ListMoreDataBase<T, K extends StatefulWidget> extends State<K> {
/// 获取异步数据
Future<List<T>> getData();
}
/// 在
mixin ListMoreDataMixin<T, K extends StatefulWidget> on ListMoreDataBase<T, K> {
@override
void initState() {
print('init');
super.initState();
initData();
}
@override
void dispose() {
print('dispose');
super.dispose();
scrollController?.dispose();
}
/// 数据列表
List<T> listData = [];
/// 分页
int page = 1;
/// 是否在加载数据
bool isLoading = false;
/// 滚动条控制器
ScrollController scrollController = ScrollController();
/// 初始化数据
Future<void> initData() async {
setState(() {
isLoading = true;
});
List<T> data = await getData();
if (!mounted) return;
setState(() {
listData = data;
isLoading = false;
});
}
/// 上拉加载更多
Future<void> loadMore() async {
setState(() {
isLoading = true;
page += 1;
});
List<T> data = await getData();
if (data.isEmpty) {
page--;
}
setState(() {
listData.addAll(data);
isLoading = false;
});
}
bool canLoadMore(ScrollNotification scroll) {
return !isLoading &&
scroll.metrics.maxScrollExtent <= scrollController.offset;
}
bool onNotification(ScrollNotification scroll) {
if (canLoadMore(scroll)) {
loadMore();
}
return true;
}
}
注:
ps:下面从简单到复杂,演示mixin在Dart中的用法
最简单的mixin
mixin TestMixin {
void test() {
print('test');
}
int testInt = 1;
void test2();
}
class Test with TestMixin {
@override
test2() {
print('test2');
}
}
void main() {
Test().test(); // test
print(Test().testInt); // 1
Test().test2(); // test2
}
mixin本身可以是抽象的,可以定义各种方法属性,也可以是抽象的,等后续类去实现
基于某个类型的mixin
class BaseObject {
void method() {
print('call method');
}
}
mixin TestMixin on BaseObject{
void test() {
print('test');
}
int testInt = 1;
void test2() {
method();
}
}
class Test extends BaseObject with TestMixin {
}
void main() {
Test().test(); // test
print(Test().testInt); // 1
Test().test2(); // call method
}
当使用on关键字,则表示该mixin只能在那个类的子类使用了,那么结果显然的,mixin中可以调用那个类定义的方法、属性
多个mixin
mixin TestMixin {
void test() {
print('test');
}
int testInt = 1;
void test2();
}
mixin TestMixin2 {
int testInt = 2;
void test3() {
print('test3');
}
}
class Test with TestMixin, TestMixin2 {
@override
test2() {
print('test2');
}
}
void main() {
Test().test(); // test
print(Test().testInt); // 2
Test().test2(); // test2
Test().test3(); // test3
}
如果把TestMixin和TestMixin2的先后顺序改一下:
mixin TestMixin {
void test() {
print('test');
}
int testInt = 1;
void test2();
}
mixin TestMixin2 {
int testInt = 2;
void test3() {
print('test3');
}
}
class Test with TestMixin2, TestMixin {
@override
test2() {
print('test2');
}
}
void main() {
Test().test(); // test
print(Test().testInt); // 1
Test().test2(); // test2
Test().test3(); // test3
}
如果mixin存在冲突的部分,后面会覆盖前面的,没有冲突的则会保留,所以可以存在后面的mixin修改了前面的mixin的一部分逻辑的情况,不需要直接继承即可实现覆盖,避免了更复杂的继承关系
"多重继承"
mixin TestMixin on BaseClass {
void init() {
print('TestMixin init start');
super.init();
print('TestMixin init end');
}
}
mixin TestMixin2 on BaseClass {
void init() {
print('TestMixin2 init start');
super.init();
print('TestMixin2 init end');
}
}
class BaseClass {
void init() {
print('Base init');
}
BaseClass() {
init();
}
}
class TestClass extends BaseClass with TestMixin, TestMixin2 {
@override
void init() {
print('TestClass init start');
super.init();
print('TestClass init end');
}
}
void main() {
TestClass();
/// TestClass init start
/// TestMixin2 init start
/// TestMixin init start
/// Base init
/// TestMixin init end
/// TestMixin2 init end
/// TestClass init end
}
稍微有点绕,可以看到,这已经事实上达到多重继承才能达到的效果了,写起来比较麻烦,某种程度上也更不容易出错(相对于C++)。。。源码里有最好也最复杂的例子—WidgetsFlutterBinding,它的定义如下:
class WidgetsFlutterBinding
extends BindingBase with GestureBinding,
ServicesBinding,
SchedulerBinding,
PaintingBinding,
SemanticsBinding,
RendererBinding,
WidgetsBinding
{
}
看完上述内容,是不是对如何使用Flutter中的mixin有进一步的了解,如果还想学习更多内容,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。