普通视图

发现新文章,点击刷新页面。
昨天以前沐凉

flutter loading 动画插件(flutter_spinkit 4.1.2)

作者 cqiang102
2020年3月29日 22:24

flutter_spinkit 4.1.2

  • pubspec.yaml 中添加依赖
    1
    2
    dependencies:
    flutter_spinkit: "^4.1.2"
  • 阅读文档,看看案例。照着实现一个最简单的例子

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'loading 动画',
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.dark,
),
home: Scaffold(
// SafeArea 异形屏适配
body: SafeArea(
// 层叠布局
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: BoxDecoration(color: Colors.white),
),
),
Positioned.fill(
child: Container(
// color: Colors.blueAccent,
color: Colors.transparent,
child: SpinKitFadingCircle(
// 可以画一个圈,分为 0 1 2 3 4 5 6 7 8 9 份
itemBuilder: (_, int index) {
return DecoratedBox(
decoration: BoxDecoration(
// isEven 表示是否整数
color: index.isEven ? Colors.red : Colors.green,
),
child: Text("$index"),
);
},
size: 120.0,
),
),
)
],
),
),
),
);
}
}
  • 模拟一个简单的场景,点击登录出现 loading 动画,一段时间后取消

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'loading 动画',
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.dark,
),
home: Scaffold(
// SafeArea 异形屏适配
body: BodyWidget(),
),
);
}
}
class BodyWidget extends StatefulWidget {
@override
_BodyWidgetState createState() => _BodyWidgetState();
}
class _BodyWidgetState extends State<BodyWidget> {
bool ifLoading = false;
Timer timer;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: BoxDecoration(color: Colors.white),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
RaisedButton(
child: Text("登录"),
onPressed: () {
print("登录啊");
setState(() {
ifLoading = true;
});
// 三秒后取消动画
timer = new Timer(Duration(seconds: 3), () {
setState(() {
ifLoading = false;
});
});
},
),
],
),
),
),
ifLoading
? Positioned.fill(
child: Container(
color: Colors.blueAccent,
child: SpinKitFadingCircle(
// 可以画一个圈,分为 0 1 2 3 4 5 6 7 8 9 份
itemBuilder: (_, int index) {
return DecoratedBox(
decoration: BoxDecoration(
// isEven 表示是否整数
color: index.isEven ? Colors.red : Colors.green,
),
child: Text("$index"),
);
},
size: 80.0,
),
),
)
: Container(),
],
),
);
}
}
  • 引入 provider 模拟更加真实的例子
    1
    2
    3
    dependencies:
    flutter_spinkit: "^4.1.2"
    provider: ^4.0.4
  • 看到的效果是一样的
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    void main() => runApp(App());
    class App extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    title: 'loading 动画',
    debugShowCheckedModeBanner: false,
    theme: ThemeData(
    brightness: Brightness.dark,
    ),
    home: Scaffold(
    // SafeArea 异形屏适配
    body: MultiProvider(
    providers: [
    ChangeNotifierProvider(
    create: (_) => LoginProvider(),
    )
    ],
    child: Consumer<LoginProvider>(builder: (context,loginProvider,_){
    return BodyWidget(ifLoading: loginProvider.ifLoading,onPressed: loginProvider.onPressed,);
    },),
    ),
    ),
    );
    }
    }
    class LoginProvider with ChangeNotifier {
    bool ifLoading = false;
    VoidCallback onPressed;
    Timer timer;
    LoginProvider() {
    onPressed = () {
    ifLoading = true;
    // notifyListeners 我的理解就是把它当做 setState 用
    notifyListeners();
    // 模拟发送网络请求异步获得请求结果
    timer = new Timer(Duration(seconds: 3), () {
    ifLoading = false;
    notifyListeners();
    });
    };
    }
    }
    class BodyWidget extends StatelessWidget {
    bool ifLoading = false;
    VoidCallback onPressed;

    BodyWidget({@required this.ifLoading, @required this.onPressed});

    @override
    Widget build(BuildContext context) {
    return SafeArea(
    child: Stack(
    children: <Widget>[
    Container(
    width: MediaQuery.of(context).size.width,
    height: MediaQuery.of(context).size.height,
    decoration: BoxDecoration(color: Colors.amberAccent),
    child: Column(
    mainAxisAlignment: MainAxisAlignment.end,
    children: <Widget>[
    RaisedButton(
    child: Text("登录"),
    onPressed: onPressed,
    ),
    ],
    ),
    ),
    ifLoading
    ? Positioned.fill(
    child: Container(
    color: Colors.blueAccent,
    child: SpinKitFadingCircle(
    // 可以画一个圈,分为 0 1 2 3 4 5 6 7 8 9 份
    itemBuilder: (_, int index) {
    return DecoratedBox(
    decoration: BoxDecoration(
    // isEven 表示是否整数
    color: index.isEven ? Colors.red : Colors.green,
    ),
    child: Text("$index"),
    );
    },
    size: 120.0,
    ),
    ),
    )
    : Container(),
    ],
    ),
    );
    }
    }

关于使用@CrossOrigin遇见的的一些问题和理解

作者 cqiang102
2019年12月6日 00:57

记录今天遇到的一个问题

个人理解 参考需谨慎。如果有错误,谢大佬指点

是关于跨域的,在昨天写项目的时候遇到的跨域请求的问题,网上通常的配置方法都是使用 过滤器,或者 实现 WebMvcConfigurer 接口的方法。相对来说有些老了。不符合我想要的效果。

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}

然后我在阅读 Spring 官网 看到有使用 @CrossOrigin 方式可以只需要加一个注解就行(简单粗暴我喜欢)。于是我便采用的这种方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@CrossOrigin(value = "*",allowCredentials = "true")
@RequestMapping("user")
public class UserController {
@PostMapping(value = "login")
public Map<String, Object> login(@RequestBody User user) {
Map<String, Object> map = new HashMap<>();
map.put("userName",user.getUserName());
map.put("userPass",user.getUserPass());
return map;
}
@PostMapping(value = "logout")
public Map logout(@RequestBody String token) {
Map<String, String> map = new HashMap<>();
map.put("token",token);
return map;
}
}

配置之后问题就来了在访问 login 接口的时候可以正常访问,但是 请求 logout接口的时候,还是出现的跨域的问题。

在反复检查配置,阅读官网后。尝试了上面的方法配置,完全没问题 (那我代码应该没问题 2333),但是换回 @CrossOrigin 依旧请求失败。

由于那种配置方法比较死,不是很灵活 (我不喜欢)。所以我想继续使用 @CrossOrigin 的方式配置。

于是便把部分代码抽取出来,单独建一个干净的项目复现刚才的问题。

按照 Spring 官网的配置方法一路通畅。于是对比这个 demo 和我原先的 项目,便发现了原因 !!!

因为我配置了一个登录拦截器,用于验证 token 。拦截器不拦截 login 方法。拦截需要验证 token 的方法,所以就出现了部分有效,部分无效的问题。
所有经过了拦截器的方法都无法访问。

好,知道了问题的所在,让我继续翻文档。。。。

了解到。@CrossOrigin 这个注解本质也是一个拦截器,往response里添加 Access-Control-Allow-Origin 等响应头信息。
如果在 controller 类上或在方法上标了 @CrossOrigin 注解,则 spring 在记录 mapping 映射时会记录对应跨域请求映射。

当一个跨域请求过来时,spring 在获取 handler 时会判断这个请求是否是一个跨域请求,如果是,则会返回一个可以处理跨域的 handler

QAQ 这时候找到 HandlerMapping 里的 getCorsHandlerExecutionChain方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
HandlerExecutionChain chain, @Nullable CorsConfiguration config) {

if (CorsUtils.isPreFlightRequest(request)) {
HandlerInterceptor[] interceptors = chain.getInterceptors();
chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
}
else {
// 写死了 index 0 emmmm
chain.addInterceptor(0, new CorsInterceptor(config));
}
return chain;
}

找到 CorsInterceptorpreHandle打上断电点,和自己的拦截器打上断点(自己的先执行,凉凉)

好像 Spring 也没给配置拦截器执行顺序的东东(菜鸡的我不知道)

到此可以知道,@CrossOrigin 是在 spring 映射 handler 的时候 干的活。那既然拦截器不行,那我就用 Spring AOP 吧 QWQ !!!
或者在拦截器中设置,只要是预请求(OPTIONS)全部直接放行

Linux 常用指令、IntelliJ IDEA 常用快捷键

作者 cqiang102
2019年11月17日 19:19

Linux 篇

  • 查询占用此端口的程序 。
    • lsof -i:{port} 。 例:lsof -i:3306
    • netstat -tunlp|grep {port} 。 例:netstat -tunlp|grep 8080
  • 查看端口使用情况 netstat -anp
  • 查看本机资源使用情况 top 或安装(apt-get install htop)htop可实时变化 。
  • 杀死进程 kill {pid} 。例:kill 7821
  • 查进程 ps aux | grep ***
  • 查日志 tail -f catalina.out
  • 打 tar 包 tar zcvf FileName.tar.gz DirName
  • 解压 tar 包 tar zxvf FileName.tar.gz
  • 修改 hostname hostnamectl set-hostname you-hostname
  • 查看网关地址 route -n
  • 配置 hosts sudo vim /etc/hosts
  • ubuntu18.04 取消 dhcp ,修改 ip 地址
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    vi /etc/netplan/50-cloud-init.yaml

    network:
    ethernets:
    ens33:
    addresses: [192.168.80.160/24]
    gateway4: 192.168.80.2
    nameservers:
    addresses: [114.114.114.114,8.8.8.8]
    version: 2

    # 使配置生效
    netplan apply
  • 查日志常用 less 的一些操作
1
2
3
4
5
6
# `G`   到日志末尾
# `?` 往上面查找
# `/` 往下面查找
# `n` 下一个匹配项
# `N` 上一个匹配项
# `j/k` 上一行/ 下一行
  • 修改系统环境变量 sudo vim /etc/proflie

  • root 账户下使用其他用户运行程序 sudo -u username /usr/bin/appname

  • 添加应用图标

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    sudo vim /usr/share/applications
    # 复制一个原来的图标,对照修改
    # 例:system-config-printer.desktop

    [Desktop Entry]
    Name=Printers # 名字
    GenericName=Printers
    X-GNOME-FullName=Printers
    Comment=Configure printers
    Exec=system-config-printer # 执行的程序
    Terminal=false
    Type=Application
    Icon=printer # 图标
    StartupNotify=true
    NotShowIn=KDE;GNOME;
    X-Ubuntu-Gettext-Domain=system-config-printer
    Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-Unity-Settings-Panel;System;Printing; # 分类
    X-GNOME-Settings-Panel=printing
    X-Unity-Settings-Panel=printing
    Keywords=Printer;Queue;Print;Paper;Ink;Toner;
    X-Desktop-File-Install-Version=0.24
  • Maven,Flutter,Java 等系统环境变量配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    vim /etc/profile

    export JAVA_HOME=/usr/local/java/jdk1.8.0_171
    export JRE_HOME=/usr/local/java/jdk1.8.0_171/jre
    export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
    export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin

    export M2_HOME=/usr/local/apache-maven-3.6.3
    export PATH=${M2_HOME}/bin:$PATH

    export PUB_HOSTED_URL=https://pub.flutter-io.cn
    export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
    export FLUTTER_HOME=/usr/local/flutter
    export PATH=${PATH}:${FLUTTER_HOME}/bin
  • 查看当前目录已经占用了多大空间,需要进入目录后输入命令 du -sh

IntelliJ IDEA 篇

  • 万能快捷键 Alt+Enter
  • XML 或者 HTML 中选中一个节点 Ctrl+W
  • 删除光标所在行 Ctrl+Y
  • 双击 Shift 搜索 。
  • 重命名 Ctrl+Shift+R
  • 返回上次查看代码的位置, Alt+Alt+
  • 折叠/ 展开代码块的快捷键 。
    • Ctrl + +/- , 当前方法展开、折叠 。
    • Ctrl + Shift + +/- , 全部展开、折叠 。
  • IDEA 内切换窗口 Ctrl + Alt + [/]
  • 关闭当前打开的文件选项卡 Ctrl + F4
  • 向下复制一行 Ctrl + D
❌
❌