现在获取数据库数据都是异步操作,不能实时获取数据 ,应该怎样的写法 可以让程序在获取数据库数据后 再往下执行后面的代码
要让程序等待获取数据之后,再执行后面的代码,可以在子线程(异步语句块)中调用非异步函数获取数据,以MySQL直链操作组件为例:
第一种方式:使用异步语句块结合“到主线程”关键字
事件 按钮1.被单击(来源对象 为 视图)
变量 mysql直链1 = 创建 MySQL直链()
异步执行首
' 查询指定数据表中年龄小于30的所有记录,返回ID,姓名,年龄
变量 查询到的数据 = (集合)mysql直链1.查询记录("数据表名称","ID,姓名,年龄","年龄 < 30")
' 从集合中循环变量或者获取某一条数据
变量 第一行数据 为 文本型[] = 查询到的数据.取项目(0)
' 执行后续不参与更新界面UI的代码...
' ...
' ...
' 如果要修改界面内容,例如:修改标签标题,按钮标题,编辑框文本内容等等
' 必须使用“到主线程”将操作切换到主线程执行,如果不需要修改界面内容,则无需切换到主线程
到主线程
编辑框1.内容 = "主线程更新数据查询结果内容"
异步执行尾
结束 事件第二种方式:使用异步语句块结合“消息句柄”组件
' 定义一个消息句柄通知UI线程更新窗口内容
变量 消息句柄1 为 消息句柄
事件 按钮2.被单击(来源对象 为 视图)
如果(消息句柄1 == 空)
消息句柄1 = 创建 消息句柄()
消息句柄1.置收到消息回调(&从子线程收到消息)
结束 如果
变量 mysql直链1 = 创建 MySQL直链()
异步执行首
' 查询指定数据表中年龄小于30的所有记录,返回ID,姓名,年龄
变量 查询到的数据 = (集合)mysql直链1.查询记录("数据表名称","ID,姓名,年龄","年龄 < 30")
' 从集合中循环变量或者获取某一条数据
变量 第一行数据 为 文本型[] = 查询到的数据.取项目(0)
' 执行后续不参与更新界面UI的代码...
' ...
' ...
' 如果要修改界面内容,例如:修改标签标题,按钮标题,编辑框文本内容等等
' 使用消息句柄发送给主线程修改
消息句柄1.发送消息(1,"待发送的数据")
异步执行尾
结束 事件
函数 从子线程收到消息(源对象 为 消息句柄,消息ID 为 整数型,数据值 为 对象)
如果(消息ID == 1)
编辑框1.内容 = "从子线程发来的数据:" + 到文本(数据值)
结束 如果
结束 函数为什么不能直接在按钮被单击时直接使用同步函数等待查询数据?
例如像这样:
事件 按钮1.被单击(来源对象 为 视图)
变量 mysql直链1 = 创建 MySQL直链()
' 查询数据
变量 查询到的数据 = (集合)mysql直链1.查询记录("数据表名称","ID,姓名,年龄","年龄 < 30")
' 等待上方代码查询完毕再执行下面的代码
' ...
结束 事件上方的代码逻辑正确,编译也是没有错误的,但是为什么在实际开发时这样不行呢?
主要原因:
因为查询记录这个操作过程的所需时间是不确定的,其整体耗时受到网络状态,机器配置,服务器响应,数据体量大小等等,在不同的环境中,可能从开始发送请求查询数据再到查询结果返回数据中间的等待时间为1-20秒不等,而在这期间,整个APP都必须一直等待其返回结果,等待过程中整个APP界面将变得无响应,卡顿,而谷歌为了避免这种情况,在安卓系统层级设置了一个阈值,APP负责渲染界面的主线程如果超过5秒未响应,则直接让APP崩溃。
而直接在按钮1被单击事件中查询数据,或发送网络请求就是由主线程执行的,如果查询时间过长,APP就会无响应,甚至崩溃。为了解决这个问题,专业的做法就是将耗时操作放在子线程中,然后需要更新界面内容的时候,切换线程到主线程更新,或者使用消息句柄发送给主线程更新。
好像可以用回调 ![[[doge]]](http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/a1/2018new_doge02_org.png)
记得在主程序里面写一个变量,表明状态。避免用户无脑刷新![[[可爱]]](http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/09/2018new_keai_org.png)