Flutter中mixin的使用詳解
mixin是什么
mixin應該怎么理解呢,對Java系出身的我來說,這是一個新概念,各類資料的介紹也沒找到一個清晰的定義。從個人理解來看,可以把它想象為Kotlin中的接口(和Java的區(qū)別是可以帶非抽象的屬性和方法),而多個mixin可以相互覆蓋以實現(xiàn)組合,提供了非常大的靈活性,也可以達到類似多重繼承的效果。
頁表頁面
這是一個普通的展示數(shù)據(jù),上拉加載更多數(shù)據(jù)的列表。
其中有一個類型為List<T>
的數(shù)據(jù)列表listData,有個page數(shù)據(jù)用于分頁,isLoading用來判斷是否正在加載數(shù)據(jù),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> { /// 獲取異步數(shù)據(jù) 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(); } /// 數(shù)據(jù)列表 List<T> listData = []; /// 分頁 int page = 1; /// 是否在加載數(shù)據(jù) bool isLoading = false; /// 滾動條控制器 ScrollController scrollController = ScrollController(); /// 初始化數(shù)據(jù) 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; } }
注:
- dart是單繼承
- 在類中,能重寫mixin的屬性和方法,并且也能用super調(diào)用miixn屬性和方法
- 上面的生命周期依次打印 init widget -> init -> dispose widget -> dispose
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本身可以是抽象的,可以定義各種方法屬性,也可以是抽象的,等后續(xù)類去實現(xiàn)
基于某個類型的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關(guān)鍵字,則表示該mixin只能在那個類的子類使用了,那么結(jié)果顯然的,mixin中可以調(diào)用那個類定義的方法、屬性
多個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的一部分邏輯的情況,不需要直接繼承即可實現(xiàn)覆蓋,避免了更復雜的繼承關(guān)系
"多重繼承" 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 }
稍微有點繞,可以看到,這已經(jīng)事實上達到多重繼承才能達到的效果了,寫起來比較麻煩,某種程度上也更不容易出錯(相對于C++)。。。源碼里有最好也最復雜的例子—WidgetsFlutterBinding,它的定義如下:
class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding { }
具體WidgetsFlutterBinding的分析就沒啦,自己看源碼去吧~~
總結(jié)
到此這篇關(guān)于Flutter中mixin的使用的文章就介紹到這了,更多相關(guān)flutter mixin使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android中實現(xiàn)延時執(zhí)行操作的方法小結(jié)
在Android開發(fā)中我們可能會有延時執(zhí)行某個操作的需求,這篇文章主要介紹了Android中實現(xiàn)延時執(zhí)行操作的幾種方法,需要的朋友可以參考下2018-10-10Android webView如何輸出自定義網(wǎng)頁
這篇文章主要介紹了Android webView如何輸出自定義網(wǎng)頁,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09Android中g(shù)son、jsonobject解析JSON的方法詳解
JSON即JavaScript Object Natation, 它是一種輕量級的數(shù)據(jù)交換格式, 與XML一樣, 是廣泛被采用的客戶端和服務端交互的解決方案.接下來由腳本之家小編給大家介紹Android中g(shù)son、jsonobject解析JSON的方法,感興趣的朋友一起學習吧2016-02-02Android進程間大數(shù)據(jù)通信LocalSocket詳解
這篇文章主要為大家介紹了Android進程間大數(shù)據(jù)通信LocalSocket詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03Android recycleView的應用和點擊事件實例詳解
這篇文章主要介紹了Android recycleView的應用和點擊事件實例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12