17-Flutter状态管理

状态管理是声明式编程非常重要的一个概念,我们在前面介绍过Flutter是声明式编程的,也区分声明式编程和命令式编程的区别。

这里,我们就来系统的学习一下Flutter声明式编程中非常重要的状态管理

一. 为什么需要状态管理?

1.1. 认识状态管理

很多从命令式编程框架(Android或iOS原生开发者)转成声明式编程(Flutter、Vue、React等)刚开始并不适应,因为需要一个新的角度来考虑APP的开发模式。

Flutter作为一个现代的框架,是声明式编程的:

图1

Read More

07-植物大战僵尸

效果图:

图1

代码:

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import pygame
import random
from pygame.locals import *

WIDTH = 1000
HEIGHT = 500

#豌豆类
class Peas:
def __init__(self):
# 豌豆图片
self.image = pygame.image.load("./res/peas.gif")
self.image_rect = self.image.get_rect()
self.image_rect.top = 200
self.is_move_up = False
self.is_move_down = False
#是否发射炮弹
self.is_shout = False

#显示
def display(self):
# 豌豆显示在页面上
screen.blit(self.image, self.image_rect)


#向上移动
def move_up(self):
if self.image_rect.top > 10:
self.image_rect.move_ip(0,-6)

#豌豆是碰上僵尸
for zombie in Zombie.zombie_list:
if(self.image_rect.colliderect(zombie.image_rect)):
pygame.quit();
exit()

#向下移动
def move_down(self):
if self.image_rect.bottom < 500:
self.image_rect.move_ip(0,6)

#豌豆碰上僵尸
for zombie in Zombie.zombie_list:
if self.image_rect.colliderect(zombie.image_rect):
pygame.quit()
exit()
#发射炮弹
def shout_bullit(self):
#创建炮弹对象
bullet = Bullet(self)
#将炮弹对象添加到集合中
Bullet.bullet_list.append(bullet)

#键盘控制
def key_control():
# 对事件的处理
for event in pygame.event.get():
#对事件的处理
if event.type == QUIT:
quit()
elif event.type == KEYDOWN: #键盘按下
#向上键
if event.key == K_UP:
#向上移动
peas.is_move_up = True
#向下键
elif event.key == K_DOWN:
#向下移动
peas.is_move_down = True
elif event.key == K_SPACE: #空格键
peas.is_shout = True

elif event.type == KEYUP:
#键盘弹起
if event.key == K_UP: #向上键
peas.is_move_up = False
elif event.key == K_DOWN: #向下键
peas.is_move_down = False
elif event.key == K_SPACE: #空格键
peas.is_shout = False


#炮弹对象
class Bullet:
# 所有的炮弹对象
bullet_list = []

# 创建炮弹的间隔时间
interval = 0

def __init__(self,peas):
self.image = pygame.image.load("./res/bullet.gif")
self.image_rect = self.image.get_rect()
self.image_rect.top = peas.image_rect.top
self.image_rect.left = peas.image_rect.right

#炮弹显示
def display(self):
# 炮弹显示在页面上
screen.blit(self.image, self.image_rect)

#炮弹移动
def move(self):
self.image_rect.move_ip(10,0)
#如果炮弹超出范围,则删除
if self.image_rect.left > WIDTH:
Bullet.bullet_list.remove(self)

for zombie in Zombie.zombie_list:
if self.image_rect.colliderect(zombie.image_rect):
Bullet.bullet_list.remove(self)
Zombie.zombie_list.remove(zombie)


#僵尸类
class Zombie:
#存放僵尸对象
zombie_list = []

#存放僵尸创建的时间
interval = 0

def __init__(self):
self.image = pygame.image.load("./res/zombie.gif")
self.image = pygame.transform.scale(self.image, (70, 70))
self.image_rect = self.image.get_rect()
self.image_rect.top = random.randint(10, HEIGHT - 70)
self.image_rect.left = WIDTH

#显示
def display(self):
# 僵尸显示在页面上
screen.blit(self.image, self.image_rect)

# 僵尸移动
def move(self):
self.image_rect.move_ip(-2, 0)
# 如果炮弹超出范围,则删除
if self.image_rect.left < -70:
Zombie.zombie_list.remove(self)

#循环僵尸,查看僵尸是否碰上炮弹
for bullet in Bullet.bullet_list:
#发生碰撞
if self.image_rect.colliderect(bullet.image_rect):
Zombie.zombie_list.remove(self)
Bullet.bullet_list.remove(bullet)

#查看僵尸是否碰上豌豆
if self.image_rect.colliderect(peas.image_rect):
pygame.quit();
exit()

if __name__ == '__main__':
#显示窗体
screen = pygame.display.set_mode(size=(WIDTH,HEIGHT))
pygame.display.set_mode()
#设置背景图片
background_image = pygame.image.load("./res/background.png")

#改变图片大小
scale_background_image = pygame.transform.scale(background_image,(WIDTH,HEIGHT))
#获取图片的位置和大小
scale_background_image_rect = scale_background_image.get_rect()

#定义两个状态,用于判断是否向下,向上移动
peas_is_move_up = False
peas_is_move_down = False

#创建一个时钟,优化运行的速度效果
clock = pygame.time.Clock()

# 创建豌豆对象
peas = Peas()

while True:
#设置背景颜色为黑色
screen.fill((0,0,0))

# 设置窗体的背景图片
screen.blit(scale_background_image, scale_background_image_rect)

# 显示豌豆
peas.display()

# 键盘控制
key_control()

if peas.is_move_up:
peas.move_up()

if peas.is_move_down:
peas.move_down()

#发射炮弹
Bullet.interval += 1
if peas.is_shout and Bullet.interval >= 20:
Bullet.interval = 0
peas.shout_bullit()

#显示所有炮弹
for bullet in Bullet.bullet_list:
bullet.display()
bullet.move()

Zombie.interval += 1
#创建僵尸
if Zombie.interval > 20:
Zombie.interval = 0
zombie = Zombie()
Zombie.zombie_list.append(zombie)

#显示所有僵尸
for zombie in Zombie.zombie_list:
zombie.display()
zombie.move()

#帧频率
clock.tick(60)

pygame.display.update()

Read More

06-模块

一.01_随机生成一个整数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#随机生成一个整数

#方式一
# import random
# num = random.randint(1,10)
# print(num)

#方式二, 导入random模块中的randint函数
# from random import randint
# num2 = randint(1,5)
# print(num2)

#方式三,导入random模块中的多个函数,
# from random import randint,choice
#导入的函数比较多,可以使用 * 代替
from random import *
num3 = randint(1,10)
print(num3)
#随机选择序列中的一个数字
print(choice([1,3,5,7,9]))

二.02_导入模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#导入模块,
# import log
# log.fun_01()
# log.fun_02()

#导入模块
# from log import fun_01,fun_02
# fun_01()
# fun_02()

# #导入模块的时候,多个模块,有相同的函数名
# # 第一: 使用import 这种导入方法
# # 第二: 要是使用了from 模块名 import 函数名 这种,可以给函数名加上一个别名
# from util import fun_01 as logFn1,fun_02 as logFn2
# from log import fun_01 as utilFn1,fun_02 as utilFn2
#
# #使用
# logFn1()
# logFn2()
# utilFn1()
# utilFn2()

# from util.logutil import fun_02
# fun_02()

三.03_包的管理_main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# #第一种导入
# import util.logutil
# import util.stringutil
#
# if __name__ == "__main__":
# util.logutil.fun_01()
# util.logutil.fun_02()
# util.stringutil.fun_01()
# util.stringutil.fun_02()


#第二种方式导入
from util import logutil
from util import stringutil

if __name__ == '__main__':
logutil.fun_01()
logutil.fun_02()
stringutil.fun_01()
stringutil.fun_02()

Read More

05-面向对象

一.01_类的定义和创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""
类名: 首字母大写,驼峰命名
模块名称:英文小写
函数名称: 英文小写,多个单词之间使用下划线 _
"""


#定义一个人类
class Person:
#pass代表先过去,以后再填充代码
pass


#创建一个对象 类名()
p1 = Person()
print(p1)
print(id(p1))
print(type(p1))

p2 = Person()

#isinstance : 某个对象是否属于这个类
print(isinstance(p2,Person))

二.02_类的属性和方法

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
"""
类 概念: 事物的特征和行为的描述
人类:
特征(属性)
name:姓名
age: 年龄
行为(方法)
eat():吃饭
sleep():睡觉
"""


#定义一个人类 Person
class Person:
#定义一个初始化方法,用来设置name 和 age
def __init__(self,name,age):
self.name = name
self.age = age


#定义一个普通的方法,定义格式和函数一样,区别:必须有一个参数self
def eat(self):
print(self)
print("吃饱喝足...玩好")

def sleep(self):
print("好好睡觉...做个美梦")

#创建对应p1
# p1 --> self
# "张三" --> name
# 18 --> age
p1 = Person("张三",18)
print("person:",p1.name,p1.age)

p1.age = 20
print("person:",p1.name,p1.age)

#将p1赋值给self
p1.eat()
p1.sleep()

三.03_老贾造车

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
"""
老贾造车:
造车 ---> 返回{"name":"FF9001", "speed":260}
驾驶 ---> 把车的信息传入到驾驶的功能里面
"""

def make_car(name,speed):
"""
:param name: 型号
:param speed: 最高时速
:return: 返回造好的车
"""
print("老贾造车")
return {"name":name, "speed":speed}


def drive(car):
print("老周驾驶老贾造的%s车,最高时速%s" %(car["name"],car["speed"]))


def main():
#造车
car = make_car("FF9001",280)
#驾驶
drive(car)

main()

Read More

04-函数

一.01_函数的定义和调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"""
函数的定义:
def 函数名([参数1,参数2,...,参数n]):
函数体
[return 值]
"""

def talk():
print("你好,兄弟")

talk()
talk()
print(type(talk))

#内置模块
import builtins
#dir 查看模块中有哪些方法和函数
print(dir(builtins))

二.02_函数的形参和实参

1
2
3
4
5
6
7
8
9
10
11
"""
形参(变量): 在定义函数的时候的参数列表,在小括号中
实参(对象):在函数调用的时候传入的一个实际的对象,会赋值给形参
"""

#这里的name,就是形参
def talk(name,age):
print("{},你好,兄弟,是不是{}岁了".format(name,age))

talk("jack",21)
talk("lucy",18)

三.03_函数的形参和实参_补充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"""
"""

def fn(x,y):
x[0] = 1
y[0] = 5
print("x:{}, y:{}".format(x,y))

a = [100]
b = [200]

#如果传递的是可变类型的数据,可能会对外面的数据值发生改变
fn(a,b)

print("a:{}, b:{}".format(a,b))

Read More

03-高级数据类型

一.01_列表的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""
列表的基本描述:
1,列表的创建方式 a = [1,2,3]
2,列表是有序的集合,可以通过索引,分片进行元素的操作
3,列表是一个可变对象,对于列表的元素,可以进行修改,删除等操作
4,列表中元素的数据类型可以是任意的数据类型,数字,字符串
5,列表可以嵌套,列表中的原酸可以是列表数据类型
6,列表中存放的是每个元素的对象的引用
7,列表的数据的表示方式是使用一对中括号[],每个元素之间使用逗号隔开
"""

list1 = [1,2,3]
print(list1)
print(type(list1))
print(len(list1))

#可变对象,长度可以修改,元素可以添加,删除,修改
list2 = [1,2,"a"]
print(list2)

list3 = [1,2,[2,3]]
print(list3)
print(len(list3))

二.02_列表的索引和分片

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
"""
"""
list1 = [1,2,3]
print("list1:",list1)

#索引操作
print(list1[1])
list1[1] = 100
print(list1)

#删除
del list1[1]
print("删除后,list1:",list1)

#分片操作, [:]操作 【:), 前包括后不包括
list2 = list1[0:2]
print("list2:",list2)
print("id,list1=,",id(list1))
print("id,list2= ",id(list2))

print("="*50)

list1[2:2] = [4,5]
print("插入之前:",list1)

#先删除,在插入 【0:)操作,在0的位置上,插入["a","b","c"]
list1[1:2] = ["a","b","c"]
print(list1)

#只删除第0个元素
list1[0:1] = []
print(list1)

#只添加操作
list1[0:0] = [100,200]
print(list1)

#for 遍历
for item in list1:
print(item)

三.03_列表的加号和乘号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""
+ 连接符
* 复制符号
"""

#必须是相同类型的序列, list()函数,可以将字符串分解成list
list1 = [1,2,3] + list("abc")
print(list1)

# * 复制符号
list2 = [1,[2]] * 2
print(list2) # [1,[2],1,[2]]

#把第一个元素改成100
list2[0] = 100
print(list2) #[100,[2],1,[2]]

#把第二个元素中的第一个元素改成200
list2[1][0] = 200
print(list2) #[100,[200],1,[200]], 这里你会发现,第2个元素和第4个元素,同时修改了值

list2[1] = [300]
print(list2) # 只改第2个元素

Read More

02-python流程控制

一.条件控制_if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"""
流程控制:
python解释器:从上往下依次顺序解释执行
顺序结构
条件判断语句
循环语句
"""

print("坐车去上班")
print("认真工作")
weather = 1 #0:天气不好 1:天气好
if weather == 0:
#缩进语句
print("去打篮球") #只有在天气好的时候才打篮球
print("回家")

二.条件控制_if_else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"""
语法格式:
if 条件1:
语句1
else:
语句2

"""
#需求: 订单金额 >= 128 EMS包邮 否则 韵达包邮
amount = int(input("请输入您的订单金额:"))
if amount >= 128:
print("金额超过128元")
print("EMS包邮")
else:
print("韵达包邮")

三.流程控制_if_elif_else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"""
如果需要有超过2个结果需要处理,我们需要使用多个条件表达式进行判断
格式:
if 表达式1:
语句1
elif 表达式2:
语句2
else:
语句3

需要:订单金额 >= 128 EMS包邮
订单金额 》 68 韵达保留
否则:邮费自理
"""

amount = int(input("请输入您的订单金额:"))
print("---------start-------------")
if amount >= 128:
print("EMS包邮")
elif amount > 68:
print("韵达包邮")
else:
print("运费自理")
print("---------end-------------")

Read More

01-python基础

一. 变量和常量

1
2
3
4
5
6
7
8
9
10
11
username = "jack"
print(username)

print(type(username))

username = 8
print(username)

print(username+5)

print(type(username))

二. 变量_对象和引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"""
操作流程
1,创建一个数字对象100
2, 创建一个变量a
3, 将100赋值给变量a
"""

a = 100
print(a)

# id(a), 变量a中所存放的内存地址
print(id(a))

a = 108
print(a)
print(id(a))

三. 垃圾回收_共享引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"""
在程序运行的过程中,把创建的对象而且已经是没有用的对象自动回收,这个过程,称之为垃圾回收
"""

a = "python"
b = a

#a, b两个变量共享引用数据 python
print(id(a))
print(id(b))

a = "wolfcode"
print(a)
print(id(a))
print(id(b))

Read More