Golang TCP 即时通讯实例

main.go package main func main(){ server := NewServer("127.0.0.1", 8888) server.Start() } server.go package main import( "fmt" "net" "sync" "io" "time" ) type Server struct { Ip string Port int //在线用户列表 OnlineMap map[string]*User mapLock sync.RWMutex //消息广播channel Message chan string } func NewServer(ip string,port int) *Server { server := &Server { Ip: ip, Port: port, OnlineMap: make(map[string]*User), Message: make(chan string), } return server } //监听Message广播消息channel的goroutine,一旦有消息就发送给全部在线的User func (this *Server) ListenMessager() { for { msg := <-this....

November 11, 2021 · 3 min · alvazu

Flutter 异步全解

一、异步入门 1.1 async和await 这两个关键词的本质是语法糖。例如: void _increment() async { await Future.delayed(Duration(seconds: 1)); setState((){ _counter++; }); } 等价于: void _increment() { Future.delayed(Duration(seconds: 1),(){ setState((){ _counter++; }); }); } 或者: void _increment() { Future.delayed(Duration(seconds: 1)).then( (value) => setState((){ _counter++; }) ); } ​ 这里需要纠正一个误区:就像JS那样,dart的异步操作并非多线程。在dart中,每一个线程都被isolate包裹,它们之间不能共享内存,也就避免了死锁问题,降低了程序复杂度,提升GC的性能。线程之间使用消息队列来通信。 ​ 一个线程怎么处理等待事件呢?这里就要用到Event Loop机制。内置一个Event Queue和MicroTask Queue,只要MicroTask Queue中还有事件没有处理完,则先处理这里面的事件,而此时EventQueue中的事件一个都不会被执行。使用scheduleMicrotask()来向Microtask Queue添加事件。 void main(){ Future(() => print('A')); print('B'); } //打印结果:BA ​ 这里我们还是要提醒一下,只有在出现需要等待的事件时,EventLoop机制才能发挥作用。如果卡顿是因为计算量过大造成的,那么只有多开几个Isolate(线程)来解决了。 1.2 运行时机 直接运行:Future.sync()、Future.value()、_.then() Microtask:scheduleMicrotask()、Future.microtask()、_completed.then() Event:Future()、Future.delayed() 1....

November 9, 2021 · 3 min · alvazu

Flutter Scrollable教程

一、基本Scrollable 1.1 Recycle ​ 类似RecyclerView,ListView会回收划出屏幕的控件,同时也会预先加载下面的几条。Flutter的回收可以使其被重复利用,也就是Recycle。缓冲区大小不是根据个数而是根据屏幕高度,大约是1/3屏幕,上下都有,可以用cacheExtent调整缓冲区高度。 1.2 分割线 ​ 可以用奇偶数来做Divider(),但这不是一个很好的方法:index会偏移。可以使用ListView.seprated来做分割线。 1.3 滚动条跳转(固定高度) ​ 指定Scrollbar()可以实现滚动条效果,但如果不添加itemCount属性,则列表无限长,即使滚动,滚动条也不会有反应;如果不指定itemExtent(这是一个主轴方向的紧约束),首先大幅跳转时会损失性能,其次滚动条可能会抖动。 1.4 Padding 在itemBuilder内加Padding,在视觉上会有padding,但在空白处可以滑动滚动; 在ListView.builder外加Padding,在视觉上有padding,空白处不可滑动; 设置ListView.builder内的padding属性,会在整个ListView上下留白,而不是元素间的空隙。可以用EdgeInsets.only(bottom: 200)来解决底部项目被FAB挡住的问题。 1.5 空白时显示其他控件 body: false ? Text("加载中") : ListView.builder 1.6 ScrollController 在ListView.builder中设置controller: _controller。例如,设置按下AppBar自动跳到顶部,可以使用以下代码: AppBar( title: GestureDetector( onTap: () { //_controller.jumpTo(0.0); _controller.animatedTo(-20.0, duration: ,curve: ); //传入负值,出现到顶上再弹回的效果 } //跳转 ) ) 有多个ListView时,也应设置对应的controller。 1.7 physics属性 ListView.builder的physics属性可以用来设置安卓或iOS风格的到顶回弹。例如physics: BouncingScrollPhysics()就是iOS风格的顶部回弹。 二、滑动事件 2.1 Scrollbar ​ 使用iOS风格的Scrollbar可以使用CupertinoScrollbar()。同时设置isAlwaysShown和controller属性可以一直显示scrollbar。 2.2 RefreshIndicator下拉刷新 可以设置color和backgroundColor等属性设置下拉刷新指示器的样式。RefreshIndicator和Scrollbar可以互相嵌套,不要求顺序。 2.3 拦截滚动事件 使用NotificationListener,在onNotication返回true拦截事件。 2.4 Dismissible ​ 在itemBuilder内返回一个Dismissible(),这里的key属性是必传的,例如UniqueKey(),设置onDismissed可以查看滑动方向并设置滑动后的操作,例如从列表中删除。...

November 8, 2021 · 1 min · alvazu

Flutter 布局全解

一、初识布局 1.1 约束(Terminology)的向下传递 ​ Flutter从一个runApp函数开始运行,例如: void main() { runApp(//1.向下Container传递紧约束:屏幕尺寸 Container(//2.向下Center传递约束,由于自身的w和h无效,因此原封不动地传递 width: 0.04,//1.来自App的约束使width失效,w=页面宽度 height: 0.08,//1.来自App的约束使height失效,h=页面高度 color: Colors.red[200], child: Center(//3.向下Container传递松约束,下限设为0 child: Container(//4.向下FlutterLogo传递紧约束:200<=h,w<=200 color: Colors.white, width: 200,//3.满足Center的约束,w=200 height: 200,//3.满足Center的约束,h=200 child: FlutterLogo( size: 10//不满足约束条件,失效,size=200 ), ), ) )); } 上面这段代码的运行结果如下图: ​ 通过读取LayoutBuilder的constrants参数,我们可以得到来自父组件的约束区间: LayoutBuilder(builder: (context, constrants) { print("constrants: $constrants"); return FlutterLogo(size: 10); }), ​ 我们可以通过Align系列控件来放松约束,例如使用Center。 1.2 SizedBox和FractionallySizedBox ​ 我们可以使用SizedBox和FractionallySizedBox来确定组件的大小,其中后者使用一个比例关系来约束。 ​ 但如果SizedBox本身受到一个紧约束,那么它也无法突破。 ​ 目前我们只能使用Align系列Widgets(比如Center)来将紧约束转换为松约束,例如将200<=h,w<=200转化为0<=h,w<=200。 Container( //向下SizedBox传递紧约束:200<=h,w<=200 width: 200, height: 200, child: SizedBox( //收到Container的紧约束 height: 100,//失效 width: 100,//失效 child: FlutterLogo(size: 10), //不满足约束条件,失效,size=200 ) 1....

November 3, 2021 · 5 min · alvazu

Flutter GridView简介

GridView import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget....

November 3, 2021 · 1 min · alvazu