Flutter中mixin的使用详解
mixin是什么
mixin应该怎么理解呢,对Java系出身的我来说,这是一个新概念,各类资料的介绍也没找到一个清晰的定义。从个人理解来看,可以把它想象为Kotlin中的接口(和Java的区别是可以带非抽象的属性和方法),而多个mixin可以相互覆盖以实现组合,提供了非常大的灵活性,也可以达到类似多重继承的效果。
页表页面
这是一个普通的展示数据,上拉加载更多数据的列表。
其中有一个类型为List
如果存在大量这种页面则可以用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'; ///列表页面 classRecommendViewextendsStatefulWidget{ @override _RecommendViewStatecreateState()=>_RecommendViewState(); } class_RecommendViewState extendsListMoreDataBasewithListMoreDataMixin { @override Future >getData()async{ Stringdata=awaitDioUtils.postHttp( "api/getOneLevel", parameters:FormData.fromMap({ 'page':page, 'limit':'10', }), ); ListViewJson_json=ListViewJson.fromJson(json.decode(data)); return_json.data; } @override voidinitState(){ print('initwidget'); super.initState(); } @override voiddispose(){ print('disposewidget'); super.dispose(); } @override Widgetbuild(BuildContextcontext){ returnScaffold( backgroundColor:Colors.white, appBar:AppBar(title:Text('返回')), body:Stack( children:
[ NotificationListener ( onNotification:onNotification, child:ListView.builder( controller:scrollController, itemCount:listData.length, itemBuilder:(BuildContextcontext,intindex)=> TeamListItem(listData[index]), ), ), isLoading?Center(child:CircularProgressIndicator()):Container() ], ), ); } }
mixin
import'package:flutter/material.dart'; abstractclassListMoreDataBaseextendsState { ///获取异步数据 Future >getData(); } ///在 mixinListMoreDataMixin
onListMoreDataBase { @override voidinitState(){ print('init'); super.initState(); initData(); } @override voiddispose(){ print('dispose'); super.dispose(); scrollController?.dispose(); } ///数据列表 List listData=[]; ///分页 intpage=1; ///是否在加载数据 boolisLoading=false; ///滚动条控制器 ScrollControllerscrollController=ScrollController(); ///初始化数据 Future initData()async{ setState((){ isLoading=true; }); List data=awaitgetData(); if(!mounted)return; setState((){ listData=data; isLoading=false; }); } ///上拉加载更多 Future loadMore()async{ setState((){ isLoading=true; page+=1; }); List data=awaitgetData(); if(data.isEmpty){ page--; } setState((){ listData.addAll(data); isLoading=false; }); } boolcanLoadMore(ScrollNotificationscroll){ return!isLoading&& scroll.metrics.maxScrollExtent<=scrollController.offset; } boolonNotification(ScrollNotificationscroll){ if(canLoadMore(scroll)){ loadMore(); } returntrue; } }
注:
- dart是单继承
- 在类中,能重写mixin的属性和方法,并且也能用super调用miixn属性和方法
- 上面的生命周期依次打印initwidget->init->disposewidget->dispose
ps:下面从简单到复杂,演示mixin在Dart中的用法
最简单的mixin
mixinTestMixin{ voidtest(){ print('test'); } inttestInt=1; voidtest2(); } classTestwithTestMixin{ @override test2(){ print('test2'); } } voidmain(){ Test().test();//test print(Test().testInt);//1 Test().test2();//test2 }
mixin本身可以是抽象的,可以定义各种方法属性,也可以是抽象的,等后续类去实现
基于某个类型的mixin
classBaseObject{ voidmethod(){ print('callmethod'); } } mixinTestMixinonBaseObject{ voidtest(){ print('test'); } inttestInt=1; voidtest2(){ method(); } } classTestextendsBaseObjectwithTestMixin{ } voidmain(){ Test().test();//test print(Test().testInt);//1 Test().test2();//callmethod }
当使用on关键字,则表示该mixin只能在那个类的子类使用了,那么结果显然的,mixin中可以调用那个类定义的方法、属性
多个mixin
mixinTestMixin{ voidtest(){ print('test'); } inttestInt=1; voidtest2(); } mixinTestMixin2{ inttestInt=2; voidtest3(){ print('test3'); } } classTestwithTestMixin,TestMixin2{ @override test2(){ print('test2'); } } voidmain(){ Test().test();//test print(Test().testInt);//2 Test().test2();//test2 Test().test3();//test3 }
如果把TestMixin和TestMixin2的先后顺序改一下:
mixinTestMixin{ voidtest(){ print('test'); } inttestInt=1; voidtest2(); } mixinTestMixin2{ inttestInt=2; voidtest3(){ print('test3'); } } classTestwithTestMixin2,TestMixin{ @override test2(){ print('test2'); } } voidmain(){ Test().test();//test print(Test().testInt);//1 Test().test2();//test2 Test().test3();//test3 }
如果mixin存在冲突的部分,后面会覆盖前面的,没有冲突的则会保留,所以可以存在后面的mixin修改了前面的mixin的一部分逻辑的情况,不需要直接继承即可实现覆盖,避免了更复杂的继承关系
"多重继承" mixinTestMixinonBaseClass{ voidinit(){ print('TestMixininitstart'); super.init(); print('TestMixininitend'); } } mixinTestMixin2onBaseClass{ voidinit(){ print('TestMixin2initstart'); super.init(); print('TestMixin2initend'); } } classBaseClass{ voidinit(){ print('Baseinit'); } BaseClass(){ init(); } } classTestClassextendsBaseClasswithTestMixin,TestMixin2{ @override voidinit(){ print('TestClassinitstart'); super.init(); print('TestClassinitend'); } } voidmain(){ TestClass(); ///TestClassinitstart ///TestMixin2initstart ///TestMixininitstart ///Baseinit ///TestMixininitend ///TestMixin2initend ///TestClassinitend }
稍微有点绕,可以看到,这已经事实上达到多重继承才能达到的效果了,写起来比较麻烦,某种程度上也更不容易出错(相对于C++)。。。源码里有最好也最复杂的例子—WidgetsFlutterBinding,它的定义如下:
classWidgetsFlutterBinding extendsBindingBasewithGestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding { }
具体WidgetsFlutterBinding的分析就没啦,自己看源码去吧~~
总结
到此这篇关于Flutter中mixin的使用的文章就介绍到这了,更多相关fluttermixin使用内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。