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;
 }
}

注:

  • dart是单继承
  • 在类中,能重写mixin的属性和方法,并且也能用super调用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本身可以是抽象的,可以定义各种方法属性,也可以是抽象的,等后续类去实现

基于某个类型的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 
{
}

具体WidgetsFlutterBinding的分析就没啦,自己看源码去吧~~

总结

到此这篇关于Flutter中mixin的使用的文章就介绍到这了,更多相关flutter mixin使用内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Flutter中mixin的使用详解的更多相关文章

  1. Flutter中文教程-Cookbook

    Flutter中文网的Cookbook中包含了在编写Flutter应用程序时常见问题及示例。设计基础使用主题共享颜色和字体样式Images显示来自网上的图片用占位符淡入图片使用缓存图Lists创建一个基本list创建一个水平list使用长列表创建不同类型子项的List创建一个gridList处理手势处理点击添加Material触摸水波效果实现滑动关闭导航导航到新页面并返回给新页面传值从新页面返回数据给上一个页面网络从网上获取数据进行认证请求使用WebSockets

  2. android-studio – 未配置Dart SDK

    Initializinggradle…

  3. 安卓 – 从一个扑动的应用程序拨打电话

    或者有更好的选择从我的应用程序拨打电话?

  4. android – 如何在Flutter中添加Webview?

    我知道可以将WebView添加为整页,但找不到任何示例代码.我假设你可以使用PageView作为它的基础,但不知道如何调用本机androidWebView并将其添加到PageView.谁能指出我正确的方向?

  5. android – 如何将消息从Flutter传递给Native?

    如果需要与特定的API/硬件组件进行交互,您如何将Flutter的信息传递回Android/Native代码?是否有任何事件频道可以通过其他方式发送信息或类似于回调?

  6. android – 如何在Flutter App中处理onPause / onResume?

    我是否过于复杂的事情?即使我的用例似乎不需要它,我仍然想知道:如何自己处理onPause/onResume事件?

  7. android – 如何使用Flutter构建Augment Reality应用程序?

    我对Android开发有一些基础知识.最近听说过Flutter并且非常有兴趣研究它.我想知道是否有可能使用颤振构建增强现实应用程序以及要实现此目的的方法?请帮忙.解决方法截至目前,颤振不支持3D.Flutter现在专注于2D,团队长期计划为颤振提供优化的3Dapi.你读了常见问题here.

  8. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  9. Flutter StreamBuilder实现局部刷新实例详解

    这篇文章主要为大家介绍了Flutter StreamBuilder实现局部刷新实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. Flutter 首页必用组件NestedScrollView的示例详解

    今天介绍的组件是NestedScrollView,大部分的App首页都会用到这个组件。对Flutter 首页必用组件NestedScrollView的相关知识感兴趣的一起看看吧

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部