每周学习第一期 (2019-01-04)

新闻

健康

学习资料

导师:“Ed,你在做什么?”我(骄傲的): “我在读一本有关使用 GWT 构建现代 Java 应用的书。”导师: “为什么?”我: “作为一名 Java 开发人员,我需要紧跟潮流。GWT 是流行趋势。”导师:“在 GWT 之前,你读过什么技术书籍?”我: “一本关于 Apache Tapestry 的 500 页的著作。 Tapestry 那时是流行趋势。”导师:“Tapestry 现在还流行吗?”我: “不流行了。现在流行 GWT。”导师:“你还可以重用 Tapestry 的技能来解决当前的问题吗?”我: “不能,现在没人用它了。”导师:“Tapestry 的知识能帮助你更好地理解 GWT 吗?”我: “不,不能。但我看到了一些重叠的模式。”导师:“那是设计模式。它们能帮你解决当前的问题吗?”我: “是的。可以解决其中许多问题。”导师:“技术变化无定,但有很多共同点。确定好优先级。将 80% 的学习时间投入到基础知识上。剩下的 20% 用于框架、库和工具。”我: “嗯…仅 20% 用于框架、库和工具?”导师:“是的。反正你在工作中解决问题的时候会学习它们。”我: “谢谢。”导师:“你以后会感谢我的。”

IT

  • 视频点位人流量分析”,基于深度学习和计算机视觉技术,可以实时统计监控视频中的经过人数及拥挤情况。也可以针对人员密集场所的监管需求,构建群体聚集分析模型,智能判断出某区域是否有拥挤堵塞、异常聚集等行为。
  • 禁入区域异常入侵预警”技术。识别系统通过深度学习人体特征和动作,能够自动发现、标记出人员的位置,当有人员异常入侵重点禁入区域时,以及异常行为时,系统可以发出自动预警。
  • 人员异常行为智能预警”系统,可以通过构建行为运动分析模型和行人姿态分析模型,智能分析判断出行人是否有快速运动、打架斗殴等异常个体和群体行为,及时向后台发出预警信息。
  • 剧烈挥手求救识别”技术,是利用深度学习人体姿态识别技术,精准识别人员向摄像头的剧烈挥手动作,当人员遇到不法侵害向摄像头剧烈挥手时,可以实时预警提醒后台人员。
  • 外观线索识别技术”,在茫茫人海中搜索一个人可以像百度查找一篇新闻那样容易。有了这个技术,可以跟踪犯罪嫌疑人到天涯海角,让不法分子再也无处遁形!而对于一些焦急寻找走失儿童的父母亲,或许将是一大福音。
    这套“行人搜索系统”的原理是,利用某一监控下的行人图像,可以在其它不同场景、不同光线、不同视角下的视频中准确搜索出该行人,并勾勒出其行动轨迹,搜索准确率可以达到90%。
  • 外观线索识别技术

    -“人员结构化智能分析”,通过图片处理性能达到20张/秒、视频处理性能最高达40路1080P的结构化服务器,能准确识别人脸、衣服颜色、出行姿态等等信息。将所有行人变成一个流动的“大数据库”,便于警方实现人员属性预警和人员属性搜索,进行更高层次的分析决策。

  • 携带物体识别技术”主要针对某些特定场所的安全监管需求,打造深度学习携带物体识别系统,当有人携带敏感物体时,系统会及时预警。

Flutter

JAVA

Gson,FastJson,Jackson,Json-lib不知道用哪个?看看性能对比
框架基于Maven构建,拆分成多个子模块,层次结构清晰。可用于所有Web应用,如企业后台管理系统、OA系统、CMS、CRM等。
框架本身集成了最新的 Flowable工作流引擎 https://www.flowable.org/ ,内置了流程流程设计器moduler,有完整的流程管理模块,可以轻松实现流程的在线设计、部署,流程发起、流程流转跟踪等一系列OA办公业务。
框架主模块包含:系统管理、流程管理、在线办公、文件管理、代码生成。系统管理子模块–用户管理、机构管理、区域管理、菜单管理、角色管理、字典管理、日志查询、连接池监视,实现权限精细控制,支持跨部门、跨公司数据权限授权。
框架支持前后端基础代码自动生成,免去重复劳动。

数据库

度 DBMS:PostgreSQL

PostgreSQL 已经连续两年赢得了“年度数据库”冠军称号。PostgreSQL 于 1989 年首次发布,今年恰好年满30岁,正处于人气高峰期,拥有一个非常活跃的社区并且没有出现丝毫“衰老”的迹象。

我们也可以看到,PostgreSQL 因其稳定性和强大的功能集而备受青睐,已成为众多开发者的首选数据库。PostgreSQL 以各种方式很好地满足了现代 DBMS 的要求。基于其坚实的 RDBMS 实现,它通过支持 JSON 数据类型和运算符扩展了其范围,从而为原本计划转向使用“文档存储”的项目提供了一个更有吸引力的选择。最近,在其发布的最新版本中,它专注于进一步提升分布式数据库的性能和对其的支持,以满足大数据场景的要求。

PostgreSQL 在 DBMS 市场中体现其成熟程度的一个强有力迹象是,DB-Engines 数据库排名中使用 PostgreSQL 作为基础技术的各种数据库管理系统。如果这些系统在其基础之上提供了重要的 DBMS 功能,我们将这些系统列为单独的条目。这些系统包括 Greenplum, EnterpriseDB, TimescaleDB, Citus 等。

Web服务端

GO

fileboy,文件变更监听通知系统,使用 Go 编写。
适用于 Hot Reload (典型的如开发go项目,无需每次手动执行 go build;又比如前端 node 打包) 或者 系统监控的场景。
v1.5 版本更新日志:
  • 增加 http 通知
  • 增加 callUrl 参数
  • 优化 command 稳定性
  • 增加 command -> delayMillSecond 参数
  • 优化 文案
  • 增加 在指定时间内堆叠的任务自动丢弃
  • 增加 version 信息
  • 优化 代码逻辑
GF(Go Frame)是一款模块化、松耦合、轻量级、高性能的Go应用开发框架。支持热重启、热更新、多域名、多端口、多服务、HTTP/HTTPS、动态路由等特性 ,并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、服务注册、配置管理、模板引擎、数据校验、分页管理、数据库ORM等等等等, 并且提供了数十个内置核心开发模块集,如:缓存、日志、时间、命令行、二进制、文件锁、内存锁、对象池、连接池、数据编码、进程管理、进程通信、文件监控、定时任务、TCP/UDP组件、 并发安全容器等等等等等等。

Docker

TOOL

mt管理器3.0永久会员破解版是专为安卓手机打造的文件管理工具,支持对所有文件进行处理,mt文件管理器还自带了编辑器、播放器、图片预览等功能,总之非常强大,赶快下载体验吧!
mt管理器3.0破解版功能
  • 像 WinRAR 那样打开 ZIP 格式文件,可以对 ZIP 内的文件进行删除、重命名、移动,添加/替换外部文件到 ZIP 中,无需解压后再重新打包,同时支持单独解压 ZIP 内的部分文件。
  • 文件复制、移动、创建软链接、重命名、删除、创建文件(夹),文件批量操作。获取 Root 权限后可访问系统目录,挂载文件系统为读写,修改文件权限和所有者。
  • 拥有图片查看、音乐播放、字体预览、执行脚本、文本对比等功能,在侧拉栏中可方便地查看存储设备、FTP连接、书签、后台、工具等。
  • 自带强大的文本编辑器,可以流畅编辑大文本文件,支持设置是否显示行号、开关自动换行、双指缩放字体大小、自动识别编码、代码语法高亮、自动缩进、正则搜索替换。
  • APK 编辑功能,主要有 DEX 编辑,ARSC 编辑,XML 编辑,APK 签名、APK 优化、APK 共存、去除签名校验、RES 资源混淆、RES 反资源混淆、翻译模式等。

2 of 3 in the series: 分享每一周

理解Flutter widget的生命周期

前言:

生命周期是一个组件加载到卸载的整个周期,熟悉生命周期可以让我们在合适的时机做该做的事情, 
flutter中的State生命周期和android以及React Native的生命周期类似。

生命周期的流程图:

大致可以分为3个阶段:
  • 初始化

  • 状态变化

  • 组件移除

初始化

State初始化时会依次执行 : 构造函数 > initState > didChangeDependencies > Widget build , 此时页面加载完成。
然后我们看一下每个函数的意义:

构造函数

调用次数:1次
这个函数严格意义上来讲不属于生命周期的一部分,因为这个时候State的widget属性为空,无法在构造函数中访问widget的属性 。但是构造函数必然是要第一个调用的。可以在这一部分接收前一个页面传递过来的数据。

initState

Called when this object is inserted into the tree.
调用次数:1次
当插入渲染树的时候调用,这个函数在生命周期中只调用一次。这里可以做一些初始化工作,比如初始化State的变量。

didChangeDependencies

Called when a dependency of this [State] object changes.
初始化时,在initState()之后立刻调用
当依赖的InheritedWidget rebuild,会触发此接口被调用
这个函数会紧跟在initState之后调用,并且可以调用BuildContext.inheritFromWidgetOfExactType,那么BuildContext.inheritFromWidgetOfExactType的使用场景是什么呢?最经典的应用场景是
new DefaultTabController(length: 3, child: new TabBar(
      tabs: [ "主页","订单","我的" ]
      .map( (data)=>new Text(data) ).toList(),
TabBar本来需要定义一个TabController,但是在外面套一层DefaultTabController就不需要定义TabContrller了,看下源码:
@override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _updateTabController();
    _initIndicatorPainter();
  }

void _updateTabController() {
    final TabController newController = widget.controller ?? DefaultTabController.of(context);
    ...
    }
注意到这里DefaultTabController.of(context)
static TabController of(BuildContext context) {
    final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);
    return scope?.controller;
  }
实际上就是调用BuildContext.inheritFromWidgetOfExactType,也就说在didChangeDependencies中,可以跨组件拿到数据。

运行时

build

调用次数:多次
初始化之后开始绘制界面,当setState触发的时候会再次被调用

didUpdateWidget

Called whenever the widget configuration changes.
祖先节点rebuild widget时调用 .当组件的状态改变的时候就会调用didUpdateWidget.
理论上setState的时候会调用,但我实际操作的时候发现只是做setState的操作的时候没有调用这个方法。而在我改变代码hot reload时候会调用 didUpdateWidget 并执行 build…
实际上这里flutter框架会创建一个新的Widget,绑定本State,并在这个函数中传递老的Widget。
这个函数一般用于比较新、老Widget,看看哪些属性改变了,并对State做一些调整。
需要注意的是,涉及到controller的变更,需要在这个函数中移除老的controller的监听,并创建新controller的监听。

组件移除

组件移除,例如页面销毁的时候会依次执行:deactivate > dispose

deactivate

Called when this object is removed from the tree.
在dispose之前,会调用这个函数。实测在组件课件状态变化的时候会调用,当组件卸载时也会先一步dispose调用。

dispose

Called when this object is removed from the tree permanently.
调用次数:1次
一旦到这个阶段,组件就要被销毁了,这个函数一般会移除监听,清理环境。

reassemble

hot reload调用
名称
状态
initState
插入渲染树时调用,只调用一次
didChangeDependencies
state依赖的对象发生变化时调用
didUpdateWidget
组件状态改变时候调用,可能会调用多次
build
构建Widget时调用
deactivate
当移除渲染树的时候调用
dispose
组件即将销毁时调用

实际场景

假设我们从A页面跳转到B页面, 那么A,B页面的生命周期会是怎样的呢?
B页面进入初始化状态,依次执行4个函数:构造函数 > initState > didChangeDependencies > Widget build , 此时页面加载完成,进入运行态。
此时A页面依次执行deactivate > build函数。注意 此时A页面并未卸载。
然后我们假设B页面只有一个按钮,点击B页面中的按钮,改变按钮的文字,会执行widget的build方法 ,(理论上也应该执行didUpdateWidget,但我这里没有)。
这时,我们点击返回键从B页面返回到A页面。
A页面重新显示,B页面开始卸载。
那么A先执行deactivate > build , 然后B页面依次执行:deactivate > dispose 。
此时A页面进入运行态,B页面移除。
本次示例B页面代码:
 /*
 * Created by 李卓原 on 2018/9/13.
 * email: zhuoyuan93@gmail.com
 *
 */

import 'package:flutter/material.dart';

class NewsDetailPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => NewsDetailState();
}

class NewsDetailState extends State<NewsDetailPage> {
  int text = 1;

  NewsDetailState() {
    print('构造函数');
  }

  @override
  void initState() {
    print('init state');
    super.initState();
  }

  @override
  void didChangeDependencies() {
    print('didChangeDependencies');
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    print('widget build');

    return Scaffold(
      body: Center(
        child: _loading(),
      ),
      appBar: AppBar(
        title: Text('咨询详情'),
      ),
    );
  }

  @override
  void didUpdateWidget(NewsDetailPage oldWidget) {
    print('组件状态改变:didUpdateWidget');
    super.didUpdateWidget(oldWidget);
  }

  @override
  void deactivate() {
    print('移除时:deactivate');
    super.deactivate();
  }

  @override
  void dispose() {
    print('移除时:dispose');
    super.dispose();
  }

  //预加载布局
  Widget _loading() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        CircularProgressIndicator(
          strokeWidth: 1.0,
        ),
        Container(
          child: Text("正在加载"),
          margin: EdgeInsets.only(top: 10.0),
        )
      ],
    );
  }
}

Tips:

下面内容来自咸鱼技术团队.
当ListView中的item滚动出可显示区域的时候,item会被从树中remove掉,此item子树中所有的state都会被dispose,state记录的数据都会销毁,item滚动回可显示区域时,会重新创建全新的state、element、renderobject
使用hot reload功能时,要特别注意state实例是没有重新创建的,如果该state中存在一下复杂的资源更新需要重新加载才能生效,那么需要在reassemble()添加处理,不然当你使用hot reload时候可能会出现一些意想不到的结果,例如,要将显示本地文件的内容到屏幕上,当你开发过程中,替换了文件中的内容,但是hot reload没有触发重新读取文件内容,页面显示还是原来的旧内容.
idChangeDependencies有两种情况会被调用。
创建时候在initState 之后被调用
在依赖的InheritedWidget发生变化的时候会被调用
正常的退出流程中会执行deactivate然后执行dispose。但是也会出现deactivate以后不执行dispose,直接加入树中的另一个节点的情况。
这里的状态改变包括两种可能:
1.通过setState内容改变
2.父节点的state状态改变,导致孩子节点的同步变化。

App生命周期

需要指出的是如果想要知道App的生命周期,那么需要通过WidgetsBindingObserver的didChangeAppLifecycleState 来获取。通过该接口可以获取是生命周期在AppLifecycleState类中。常用状态包含如下几个:
名称
状态
resumed
可见并能响应用户的输入
inactive
处在并不活动状态,无法处理用户响应
paused
不可见并不能响应用户的输入,但是在后台继续活动中
一个实际场景中的例子:
在不考虑suspending的情况下:
从后台切入前台生命周期变化如下: AppLifecycleState.inactive->AppLifecycleState.resumed;
从前台压后台生命周期变化如下: AppLifecycleState.inactive->AppLifecycleState.paused;

本文主要梳理一下StatefulWidget和StatelessWidget的生命周期

微组件

StatelessWidget

  1. 接收外部数据
  2. 执行部件构造方法
  3. 传入数据改变时会重新渲染UI

StatefulWidget

  1. 接收外部数据
  2. 执行部件构造方法和状态初始化方法
  3. 传入数据和 本类数据改变时都会重新渲染UI
这用到之前写的一个例子01_widget_basic
第一次运行项目

  1. ProductsManager部件初始化
  2. 创建ProductsManagerState
  3. 调用ProductsManagerState中的initState方法
  4. ProductsManagerState渲染
  5. Products部件初始化
  6. Products渲染
    当点击add product按钮数据发生改变时
    1.数据_products发生了变化 通过setState方法通知数据发生了改变 ProductsManagerState build方法被调用
  7. 而Products进行了重新构造,也就是说当外部数据变化时 Products中的 _products 直接被替换成传入的新数据而不是在修改原有数据
flutter拥有类似于react-native的状态机刷新机制,得益于分离出了StatelessWidget和StatefulWidget,资源分配更加合理的了,代码思路也清晰很多.
lutter中的视图Widget像Android中的Activity一样存在生命周期,生命周期的回调函数体都在State中。


组件State的生命周期整理:

创建阶段

Log所示:
image.png

Widget状态改变

操作:横竖屏切换
Log所示:
其他生命周期并没有执行
竖屏切换到横屏执行2次
横屏切换到竖屏执行2次
image.png

App切后台,再切回来

Log所示:
image.png

销毁阶段

Log所示:
image.png
流程如图:
image.png

import 'package:flutter/material.dart';

class LifecycleAppPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _LifecycleAppPageState('构造函数');
  }
}

class _LifecycleAppPageState extends State<LifecycleAppPage>
    with WidgetsBindingObserver {
  String str;

  int count = 0;

  _LifecycleAppPageState(this.str);

  @override
  void initState() {
    print(str);
    print('initState');
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeDependencies() {
    print('didChangeDependencies');
    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(LifecycleAppPage oldWidget) {
    print('didUpdateWidget');
    super.didUpdateWidget(oldWidget);
  }

  @override
  void deactivate() {
    print('deactivate');
    super.deactivate();
  }

  @override
  void dispose() {
    print('dispose');
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.inactive:
        print('AppLifecycleState.inactive');
        break;
      case AppLifecycleState.paused:
        print('AppLifecycleState.paused');
        break;
      case AppLifecycleState.resumed:
        print('AppLifecycleState.resumed');
        break;
      case AppLifecycleState.suspending:
        print('AppLifecycleState.suspending');
        break;
    }

    super.didChangeAppLifecycleState(state);
  }

  @override
  Widget build(BuildContext context) {
    print('build');
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('lifecycle 学习'),
        centerTitle: true,
      ),
      body: new OrientationBuilder(
        builder: (context, orientation) {
          return new Center(
            child: new Text(
              '当前计数值:$count',
              style: new TextStyle(
                  color: orientation == Orientation.portrait
                      ? Colors.blue
                      : Colors.red),
            ),
          );
        },
      ),
      floatingActionButton: new FloatingActionButton(
          child: new Text('click'),
          onPressed: () {
            count++;
            setState(() {});
          }),
    );
  }
}

class LifecyclePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      body: new LifecycleAppPage(),
    );
  }
}


6 of 7 in the series: Fltter移动开发相关

超声工作站

每周学习第一期 (2018-11-26)

新闻

三农相关

环保相关

IT相关

常用软件

技术文章资料

RPC (Remote Procedure Call)即远程过程调用,是分布式系统常见的一种通信方法,已经有 40 多年历史。当两个物理分离的子系统需要建立逻辑上的关联时,RPC 是牵线搭桥的常见技术手段之一。除 RPC 之外,常见的多系统数据交互方案还有分布式消息队列、HTTP 请求调用、数据库和分布式缓存等。

Taro 是什么?

Taro 是由凹凸实验室打造的一套遵循 React 语法规范的多端统一开发框架。
现如今市面上端的形态多种多样,Web、App 端(React Native)、微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。
使用 Taro,我们可以只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信小程序、H5、App 端等)运行的代码。同时 Taro 还提供开箱即用的语法检测和自动补全等功能,有效地提升了开发体验和开发效率
uni-app是一个使用 Vue.js 开发跨平台应用的前端框架,开发者编写一套代码,可编译到iOS、Android、H5、小程序等多个平台。
pring Boot通过提供开箱即用的默认依赖或者转换来补充Spring REST支持。在Spring Boot中编写RESTful服务与SpringMVC没有什么不同。总而言之,基于Spring Boot的REST服务与基于Spring的REST服务完全相同,只是在我们引导底层应用程序的方式上有所不同。
1.REST简短介绍
REST代表Representational State Transfer. 是一种架构风格,设计风格而不是标准,可用于设计Web服务,可以从各种客户端使用.
基于REST的基本设计,其是根据一组动词来控制的操作
使用java开发设计六大基本原则(摘自阿里巴巴java开发规范)

设计模式的六大原则:

总原则-开闭原则

对扩展开放,对修改封闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。

想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。

1、单一职责原则

不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,否则就应该把类拆分。

2、里氏替换原则(Liskov Substitution Principle)

任何基类可以出现的地方,子类一定可以出现。里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

里氏代换原则是对“开-闭”原则的补充。实现“开闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。里氏替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。

3、依赖倒转原则(Dependence Inversion Principle)

面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

4、接口隔离原则(Interface Segregation Principle)

每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

5、迪米特法则(最少知道原则)(Demeter Principle)

一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。

6、合成复用原则(Composite Reuse Principle)

尽量首先使用合成/聚合的方式,而不是使用继承。
RedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件,支持Windows 、Linux、Mac三大系统平台,RedisPlus提供更加高效、方便、快捷的使用体验,有着更加现代化的用户界面风格。该软件支持单机、集群模式连接,同时还支持SSH(单机、集群)通道连接。RedisPlus致力于为大家提供一个高效的Redis可视化管理软件。
本文解决跨域中的 get、post、data、cookie 等这些问题
TIMO后台管理系统,基于SpringBoot 2 + Jpa + Thymeleaf + Shiro 开发的通用型后台管理,采用分模块的方式便于开发和维护,目前已开发的功能:权限管理、字典管理、日志记录、代码生成,可以直接作为一个后台管理系统的脚手架!
SpringBoot-Plus 是一个基于SpringBoot 2 的管理后台系统,包含了用户管理,组织机构管理,角色管理,功能点管理,菜单管理,权限分配,数据权限分配,代码生成,子系统生成,文档管理和预览等功能.不同于其他简单的开源后台管理系统,Plus具备适当的企业应用深度
springboot有提供AbstractRoutingDataSource#determineCurrentLookupKey抽象方法去指定数据源,我们要做的就是实现切换数据源的逻辑;通过AOP在调用数据库之前切换数据源;

Android相关

1.我是怎么破解一个答题微信小程序的

此文相关资料

android 自动化 Uiautomator 的插件

Chrome使用相关

C:\Users\{%user%}\AppData\Local\Google\Chrome\User Data\Default\Bookmarks

java相关

.Net相关


3 of 3 in the series: 分享每一周

TextField多行操作


new TextField(
  keyboardType: TextInputType.multiline,
  maxLines: whatever,

Continue reading

2 of 7 in the series: Fltter移动开发相关

sqflite操作相关

SQLite 插件 同时支持 iOS 和Android.
    • 支持事务和批处理
    • 版本开放自动管理
    • 增删改查助手
  • iOS 和 Android的后台线程中执行的DB操作

开始

在您的flutter项目中添加依赖项:
dependencies:
  ...
  sqflite: any

引用示例

Import sqflite.dart
import 'package:sqflite/sqflite.dart';

原始的Sql查询

执行原始SQL查询的示例代码
// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'demo.db');

// Delete the database
await deleteDatabase(path);

// open the database
Database database = await openDatabase(path, version: 1,
    onCreate: (Database db, int version) async {
  // When creating the db, create the table
  await db.execute(
      'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)');
});

// Insert some records in a transaction
await database.transaction((txn) async {
  int id1 = await txn.rawInsert(
      'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');
  print('inserted1: $id1');
  int id2 = await txn.rawInsert(
      'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)',
      ['another name', 12345678, 3.1416]);
  print('inserted2: $id2');
});

// Update some record
int count = await database.rawUpdate(
    'UPDATE Test SET name = ?, VALUE = ? WHERE name = ?',
    ['updated name', '9876', 'some name']);
print('updated: $count');

// Get the records
List<Map> list = await database.rawQuery('SELECT * FROM Test');
List<Map> expectedList = [
  {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789},
  {'name': 'another name', 'id': 2, 'value': 12345678, 'num': 3.1416}
];
print(list);
print(expectedList);
assert(const DeepCollectionEquality().equals(list, expectedList));

// Count the records
count = Sqflite
    .firstIntValue(await database.rawQuery('SELECT COUNT(*) FROM Test'));
assert(count == 2);

// Delete a record
count = await database
    .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']);
assert(count == 1);

// Close the database
await dat


SqlHelper(助手)

使用助手的示例
inal String tableTodo = 'todo';
final String columnId = '_id';
final String columnTitle = 'title';
final String columnDone = 'done';

class Todo {
  int id;
  String title;
  bool done;

  Map<String, dynamic> toMap() {
    var map = <String, dynamic>{
      columnTitle: title,
      columnDone: done == true ? 1 : 0
    };
    if (id != null) {
      map[columnId] = id;
    }
    return map;
  }

  Todo();

  Todo.fromMap(Map<String, dynamic> map) {
    id = map[columnId];
    title = map[columnTitle];
    done = map[columnDone] == 1;
  }
}

class TodoProvider {
  Database db;

  Future open(String path) async {
    db = await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      await db.execute('''
create table $tableTodo ( 
  $columnId integer primary key autoincrement, 
  $columnTitle text not null,
  $columnDone integer not null)
''');
    });
  }

  Future<Todo> insert(Todo todo) async {
    todo.id = await db.insert(tableTodo, todo.toMap());
    return todo;
  }

  Future<Todo> getTodo(int id) async {
    List<Map> maps = await db.query(tableTodo,
        columns: [columnId, columnDone, columnTitle],
        where: '$columnId = ?',
        whereArgs: [id]);
    if (maps.length > 0) {
      return Todo.fromMap(maps.first);
    }
    return null;
  }

  Future<int> delete(int id) async {
    return await db.delete(tableTodo, where: '$columnId = ?', whereArgs: [id]);
  }

  Future<int> update(Todo todo) async {
    return await db.update(tableTodo, todo.toMap(),
        where: '$columnId = ?', whereArgs: [todo.id]);
  }

  Future close() async => db.close();
}

Transaction

不要使用数据库,而只在事务中使用Transaction对象来访问数据库
await database.transaction((txn) async {
  // Ok
  await txn.execute('CREATE TABLE Test1 (id INTEGER PRIMARY KEY)');
  
  // DON'T  use the database object in a transaction
  // this will deadlock!
  await database.execute('CREATE TABLE Test2 (id INTEGER PRIMARY KEY)');
});

批处理支持

为了避免频繁的交互,可以使用Batch:
batch = db.batch();
batch.insert('Test', {'name': 'item'});
batch.update('Test', {'name': 'new_item'}, where: 'name = ?', whereArgs: ['item']);
batch.delete('Test', where: 'name = ?', whereArgs: ['item']);
results = await batch.commit();
获取每个操作的结果都会带来成本(插入的id和更新和删除的更改的数量),尤其是在执行额外SQL请求的Android上。如果不关心结果并担心消耗大量资源和性能,可以使用
await batch.commit(noResult: true);
警告,在事务期间,在提交事务之前不会提交批处理
wait database.transaction((txn) async {
  var batch = txn.batch();
  
  // ...
  
  // commit but the actual commit will happen when the transaction is commited
  // however the data is available in this transaction
  await batch.commit();
  
  //  ...
});
默认情况下,一遇到错误(通常恢复未提交的更改),批处理就停止。您可以忽略错误,即使碰到一个操作失败,也能运行和提交操作成功每个提交:
await batch.commit(continueOnError: true);

表和列名

一般来说,最好避免对实体名称使用SQLite关键字。如果使用下列名称中的任何一个:
"add","all","alter","and","as","autoincrement","between","case","check",
"collate","commit","constraint","create","default","deferrable","delete",
"distinct","drop","else","escape","except","exists","foreign","from",
"group","having","if","in","index","insert","intersect","into","is",
"isnull","join","limit","not","notnull","null","on","or","order",
"primary","references","select","set","table","then","to",
"transaction","union","unique","update","using","values","when","where"

助手会逃避这个名字,如。。
db.query('table')
以上这行代码将等同于手动在表名周围添加双引号(令人困惑的是,这里命名的表),等同于如下代码
db.rawQuery('SELECT * FROM "table"');
但是在任何其他原始语句(包括order.、where、group.)中,确保使用双引号正确地转义名称。例如,参见下面,列名组在列参数中没有转义,而是在where参数中转义
db.query('table', columns: ['group'], where: '"group" = ?', whereArgs: ['my_group']);

SQLite 支持的数据类型

Sqlite还没有对值进行有效性检查,因此请避免不支持的类型

DateTime

SQLite不支持DateTime类型。我个人将它们存储为int(.sSinceEpoch)或string(iso8601)

Bool

SQLite不支持bool类型。使用整数和0和1值。

INTEGER

    • Dart type: int
  • 取值范围: 从-2^63 到 2^63 – 1

REAL

  • Dart type: num

TEXT

  • Dart type: String

BLOB

    • Dart type: Uint8List
  • Dart type List<int> 是支持的,但是不推荐使用 慢速转换)

当前问题

    • Due to the way transaction works in SQLite (threads), concurrent read and write transaction are not supported. All calls are currently synchronized and transactions block are exclusive. I thought that a basic way to support concurrent access is to open a database multiple times but it only works on iOS as Android reuses the same database object. I also thought a native thread could be a potential future solution however on android accessing the database in another thread is blocked while in a transaction…
  • Currently INTEGER are limited to -2^63 to 2^63 – 1 (although Android supports bigger ones)
上述机翻
由于事务在SQLIT(线程)中的工作方式,不支持并发读写事务。所有调用当前都是同步的,事务块是独占的。我认为支持并发访问的基本方法是多次打开数据库,但是它只能在iOS上工作,因为Android重用了相同的数据库对象。我还认为本机线程可能是未来可能的解决方案,但是当android访问另一个线程中的数据库时,在事务中会阻塞……
目前INTEGER被限制在-2^63到2^63-1(尽管Android支持更大的)

更多

相关类库


by phoenix翻译,原文转自

1 of 7 in the series: Fltter移动开发相关

实体类自动生成工具的配置

1.实体类自动生成

a.在线实体类处自动生成

1).JsonToDartClass转换地址-1:

2).JsonToDartClass转换地址-2:

b.离线实体类自动生成工具

Formatter是开源的,项目地址;https://github.com/debuggerx01/JSONFormat4Flutter

2.使用工程自动生成代码

参考资料

操作步骤

    1. 工程依赖中加入依赖库
      dependencies: 
        cupertino_icons: ^0.1.2 
        fluttertoast: ^2.0.3
        json_annotation: ^1.2.0
      dev_dependencies:
        build_runner: ^0.10.1+1
        json_serializable: ^1.1.0
      
    1. 建立需要生成的实体类
      import 'package:json_annotation/json_annotation.dart';
      
      part 'User.g.dart';
      
      @JsonSerializable()
      class User {
        User(this.id,
            this.username,
           ...
       );
       
        String username; 
      。。。
        factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
      
        Map<String, dynamic> toJson() => _$UserToJson(this);
      
        // 命名构造函数
        User.empty();
      
      }
      
  1. 在控制台输入生成命令
    flutter packages pub run build_runner build
    

5 of 7 in the series: Fltter移动开发相关

七大因素导致PACS系统效率低下

当今,图像存储与传输系统(Picture Archiving and Communication Systems,PACS)的出现将改变现在放射科的组成,关系到放射科在整个医院诊断链和治疗链中的地位。然而,就当前的现状而言,PACS并没能充分体现出其应有的价值,具体反映在它的工作效率没能得到很好的发挥,其价值没能够得到很好的体现。为此,本文就上述问题来探讨影响PACS的一些相关因素。

构建PACS系统

PACS基本功能包括:图像及相关信息存储、无胶片诊断、图像处理、低成本复制、复合影像诊断、远程传输、设备集群使用。PACS各组成部分的界定:1、信息系统的接口–保证病人资料可以通过各种平台,避免反复复制数据入路所耗费的重复劳动。2、数据网络–将病人信息从计算机起始单元传送到医院/校园/地区乃至世界的各个用户。3、数据库–把不同设备来源的数据有机地组成一个整体,用于不同目的的查询。4、数据采集点–CT/MRI/核医学/CR/DR/DSA/超声/数字化仪。5、存储设备–用于存储的各种不同介质。6、输出设备–硬拷贝(胶片或纸张打印)/软拷贝(工作站的显示和诊断)。因此,作为一个有价值的PACS系统应该包括以下子系统:1、直观、友好、美观的用户界面,力图使庞大的数据库信息一目了然,保证一个完整的工作流程无须在多个程序界面上反复切换;2、计算机辅助诊断和报告自动生成系统;3、三维重建可视化系统;4、医院信息管理系统(Hospital Information System,HIS)接口。

临床忽视工作流程 导致PACS效率低下

尽管PACS有着众多的理论优势,但在进行无胶片化的运作过程中,虽然降低了与胶片有关的成本而节约了资金,且使医学影像更加贴近临床医生,临床医生也从来没有像今天这样依赖于医学影像。但所有这些并没有能够使成本完全节约,没有能够全面地提高医学影像学专家及其相关的工作人员之间的工作效率,在很大程度上这不仅仅反应在PACS购置上的类型差异上,更多地反应在人们把PACS作为一种工具使用时其工作流程上的差异。

使用PACS设备最常见的错误之一是在使用PACS前没能认真思考其工作流程对医学影像科仍至整个医院的工作效率及其经济效益,此工具没有恰如其分地集成到医院各科室工作之间的流程中去,从而致使PACS相关的潜在收获没能实现。一些单位在建立无胶片化放射科之后,几乎完全模仿以胶片为基础的放射科的工作模式,在科室工作的流程方面几乎没有任何改变。在许多数字化医学影像科室中,医学影像的相关检查仍然用纸张去申请、去预约,病人及其相关的背景资料和临床信息需要重新输入到电脑的信息系统中,待打印出此信息后,再拿着这张单子给技术员。然后,再一次地人工重新打印病人身份及其相关的医学信息到医学影像科的工作站中(如:CT扫描仪操作控制台)。为了更能全面地对医学影像进行判读,须将医学影像及其相关的旧信息发给专门的工作站,这是手工或半手工的过程,与观片灯上看片没有太大的不同。放射学家需要拿着这张申请单,打印病人的ID号、姓名,或从条形码判读这些信息。报告往往写在纸上,或采用传统打印机进行打印。这种打印纸的报告单的分类、传递仍就是由人工去陆续放入病人的病历夹中。这种运行方式非旦没能提高工作效率和节约资金,相反,还增加了相关的设备成本及人员的补充。

尝试改进PACS工作流程

当医学影像科进行细致的工作流程分析和重新设计工作流程去展示PACS的优势时,可最大限度地提高效率和节约成本,也只有将PACS的实施汇集到医院及放射信息系统中,转变电子医疗记录的使用可便于发展流水线样更有效的系统。医生可以采用位于各自医疗中心的各个工作站去申请影像检查,这些指令在PACS数据库中自动产生电子文件夹,并启动自动检索过去的资料进行比较研究(可进行以前3个月以上的资料检索),由工作站快速检索长期档案到短期档案(研究以前3个月以上的资料)。利用一种叫做模态工作菜单的功能可使这些指令加入到电子医疗记录或医院信息系统(Hospital Information System,HIS)中去,或自动地加入(依据成像方式),或从各种不同成像模式中由技术员抽取它们。放射学家便可在他们的PACS工作站中判读检查的项目。每位放射学家可确定检查的类别(根据方式或解剖区域,或这些的组合)以显示在他或她的工作菜单中,此可消除打印需要或从一张纸中需要条形码获得病人的信息。

改进工作流程 PACS每天为临床医生节约15分钟

在医院和放射信息系统之间能够既有信息又有影像自动化流程,PACS、成像方式、录入系统导致消除大部分在以胶片为基础的系统中所需要的各个人工步骤,这种工作流程的重新设计可使临床大夫、职员、放射学家、技术员、录入员的工作效率明显提高。有资料表明:改变与PACS使用相关的工作流程可使技术员的效率增加20-60%,职员效率增加50%以上,放射医师的工作效率增加40%以上,而自动影像显示增加放射医师的判读效率在10%以上。临床大夫们指出,由于改变了无胶片化科室管理的相关工作流程,一般他们一天节约45分钟以上。仅工作菜单方式的使用在传递CT扫描到PACS中错误率从8%降到约1.5%。

{#page#}

PACS的难题:信息交换标准

然而,PACS、成像方式、录入系统与电子医疗记录或医院信息系统/放射信息系统(HIS/ RIS)的集成是困难的,因为它需要HIS/RIS和成像方式之间的连接水平,这在大多数单位目前不能得到。在这种情形下的两个主要问题:首先是缺乏信息交换功能,例如在当前放射科模式工作菜单和核医学成像系统的这种层次水平上的集成;第二是这种方式在使用的标准上缺乏一致性。这些标准本身在它们执行中具有较强的灵活性。尽管使用这些标准,但它可导致“理想发射”通讯在方式、PACS、HIS/RIS之间的不匹配。

用于病人和研究信息这种通讯的两种最普通的标准是数字成像和医疗通讯(Digital Imaging and Communications in Medicine,DICOM)与健康水平7(Health Level Seven,HL-7)。尽管在放射科和核医学模式中几乎都支持DICOM,但许多HIS,甚至RIS厂商在他们的系统中仅提供少量的DICOM能力。这里一定要注意的是,一些厂家PACS系统虽然采用国际电子通讯技术标准–DICOM网关和HL7引擎,作为对外的DICOM和HL7接口,而系统内部仍然采用非标准的体系,这样的产品很难保证其影像高质量的传输和存储以及各方面的兼容性。所以,仅有一小部分放射科和核医学科或门诊中心能够利用DICOM模式工作菜单功能,而得益于工作流程的节约。

PACS对CRT的要求

随着终端技术的发展,医学影像科大夫与临床医生即可坐在各自的办公桌前,甚至是家中随意调取病人的图像资料,显示在终端显示器上,进行诊断或浏览,但对于不同用途的显示器有着不同的要求,正确、合理地配置显示器,对PACS的建设和应用有着重要作用。通常考察显示器的性能主要从以下几个参数进行:空间分辨率、灰度分辨率、低对比分辨率、几何畸变、亮度、尺寸、刷新率、带宽等。

CRT选购的关键在于其用途是什么,如:对于CR、DR要求显示器空间分辨率至少达1KX1K,灰度分辨率至少达10bit,刷新率85HZ,相应带宽高于150M。对于乳腺X片影像,显示器空间分辨率应大于2KX2K,灰阶达12bit,刷新率保持,带宽也相应提高。CT、MR:灰度分辨率最好达12bit,空间分辨率1K即可。DSA:空间分辨率达1K,灰度分辨率不小于8bit,由于DSA有时显示的是高达40帧/秒的动态图像,所以对刷新率有较高的要求,大于100HZ。

医学影像数据量庞大

PACS能够显示各种医学影像,可以调整显示的分格,并可单独对每幅图像进行处理,包括:图像放大、缩小、增强、锐度调整、以及漫游等,图像面积、周长、灰度等的测量,并具有对医学图像进行后处理和统计分析的各种功能,电影回放、三维重建、多切面重建等。这首先要求有大容量存贮器,图像的存储需要解决在线浏览30天左右的所有住院病人的图像,以大容量的阵列硬盘作为存储介质;对半年至一年的图像资料采用磁光盘存储;超过一年的图像资料以磁带、DVD、或CD-R等介质存储,需手工检索。采用分层存贮策略来满足PACS的要求,即将PACS中的图像分轻重缓急分别存于高速缓存(RAM存贮,即随机存贮器)、前台(高速磁盘)和后台(光盘塔或库)存贮器中,使用较多的或刚刚产生的图像应存于前台存贮器中,不常使用或过期的图像应将其归档并存于光盘中。医学图像按一定的方式存贮在病人数据库中,存贮前作分类、编排、索引、文字说明或其他形式的再处理。

但是,医学影像的数据量太大,一幅CR或DR的胸片,要达10-16MB,1例DSA的资料可达GB数量级,且还有多种新的成像设备在不断投入使用,因此,医学影像的数据量还在急剧上升。所以,PACS应充分考虑其前、后向的兼容性,系统可以在业务量扩大时平滑扩容。现今,CR图像为8MB、DR图像16MB,数字化乳腺图像可达到40MB,医院每天可产生达到几个GB的数据,因此必须有大容量PACS服务器才能支持。

PACS本身是一种专用的计算机网络,对其中的信息压缩是提高PACS效率的重要途径,因此图像的信息压缩也变成了医学图像传输中的重要问题。目前公认的压缩标准为JPEG(JointPhotographic Expert Group,联合图片专家组)和MPEG(Moving Picture Expert Group,运动图像专家组),近来另一压缩Wavelet被应用于高分辨率医学影像的压缩(Mammography和X-ray),JPEG不仅极易应用于PACS,而且适用于CT、MRI、DSA等一切图像及真彩色图像的压缩。目前图像的压缩还面临两个方面的问题,一是影像的压缩分为无损压缩(Lossless compression)和有损压缩(Lossy compression),无损压缩的图像可完全复原,几乎没有信息的丢失,诊断的准确性高,但压缩的图像十分有限,二维情况下仅在1.5:1-3:1之间,占用的存储空间大,长此以往会影响PACS的工作效率以及对使用低速率通讯媒体的Teleradiology存在用户接受度的问题;而有损压缩的图像有信息丢失或失真,但压缩比可达10:1-20:1,占用的存储空间小,具有一定的经济性和实用性。另一个问题是计算机速度,用软件压缩或解压缩常要占据计算机的宝贵时间以及系统资源,且很难做到实用,用硬件压缩速度较快,但将增加PACS的成本。因此,选择哪一种影像信息的压缩方式要根据原始图像是否有保存价值、影像诊断的准确性等实际情况来决定。

改善教学环境

放射学家因为缺乏提取和存贮感兴趣影像的一种简单系统而受到长期困扰。单纯采用观片灯、三角架、相机和暗室去收集各种不同疾病的影像范例导致大量诸如此类的影像丢失。拷贝胶片以其产生、笨重的管理和存贮以及难以携带而付出代价。PACS的出现带来胶片极快及灵活的显示。然而,大多数PACS系统没能提供为临床PACS环境以外提取使用影像的有效方法而令许多放射学家失望。结果,许多放射学家必须承担分离、费时的步骤去提取DICOM影像,或从他们的PACS中提取其他所有人的影像,下载它们到可移动的媒体,然后将这些影像转换成更好使用的格式,如jpg格式。

任何网上个人电脑上(PC)的任何数字影像能被拷贝到影像服务器,然后可用于数字教学档案、演讲或出版。影像可被编入显示的软件如PowerPoint或为了教学回顾储存在CD上(Compact Disks压缩盘、光盘),或在单位以外的地方展示。可提供灵活的输出选择:影像可存贮到一个服务器上、一个网络硬件驱动器、一个局域硬件驱动器、一个光盘、一个软盘、甚至一个e-mail附属装置。

人们用屏-提取软件提取影像,整个提取过程在5-10秒之间,造成可忽略的工作流的干扰。用户可接着在服务器上打开影像,以管理、存贮、分类及显示它们。如果用户正在创建一个正式教学文档,影像可直接从具备教学文档软件的服务器中提取,即时经验较少的用户也能够接受无损选择。它可在windows95/98/Me/NT4.0/2000或后来版本的任何PC机上运行。

可建立一个小的工作站–服务器作为一个影像库可在PACS与医院网络之间充当一个桥梁。从PACS工作站中拷贝影像并存贮在影像库工作站–服务器中。任何医院网络–连结的PC可接近影像库服务器。此外,用户能够进入由一个虚拟私人网(Virtual Private Network,VPN)连结的医院外影像库服务器,通过路径联络安全通过医院防火墙。然后可操作、存贮影像,并进入数字格式。

PACS系统安全存在隐患

数据的安全在网络的使用中是第一位的,没有安全性的网络是没有意义的。医学图像的安全性应包括如何保护病人的隐私和医生自身的安全性。在医院信息服务集团应保持一个防火墙防止和控制所有内网进入。PACS网和医院网络都由此防火墙防范。这样,尽管用影像服务器在二个网络间架桥,但没有涉及病人的秘密或影像安全。为了保护病人的秘密,在提取的影像区域内没涉及病人姓名、医学记录号码。也避免用诸如身份信息命名无保证的影像文件。授权的用户仅采用VPN可进入医院网络影像服务。可给指定个人特权和口令进入主VPN,以便他们在其办公室或家中的计算机上能够显示和下载影像。这些用户能从家中回顾影像、丰富讲义、建立教学文档。

医院建PACS系统需要可靠的合作伙伴

PACS系统可持续性发展具体的一点就是应具有二次开发的能力,解决或升级周期短,因为医院建立PACS不是最终目的,最终要实践电子病历,要完全以电子的方式在医院内部被高效地管理和传输。这是一门集医学、放射影像学、数字化影像技术、计算机技术、网络通信技术的综合学科,更是一项包括实施和服务的系统工程。

因此,寻找可靠的集成商作为合作伙伴必须具备下列条件:1、必须有良好的企业资质及社会形象;2、对PACS的集成设计有一定的经验,具体应体现在国内有成功的案例可供考察、论证及比较;3、具有深厚的行业背景、技术积累及工程经验,对各种影像设备的连接驾轻就熟,对各种非医学数字成像通讯标准(Digital Imaging Communication in Medicine,DICOM)设备能够顺利地构成互联互通的完整系统;4、能充分了解我国的医疗模式及本院的运行机制,从而能提供全面的架构设计及提供解决、克服障碍因素的解决方案;5、对系统运行过程中出现的障碍及设备的故障,必须具有在第一时间内做出响应并能及时排除障碍,使系统及时恢复正常运行的能力;6、能为系统提供长期维护及主动提供扩容、升级等信息并承担工程;7、具有PACS与HIS无缝集成的能力;8、有丰富的国际采购经验及畅通的采购渠道。为此,选择一个具有相应技术实力,了解本医院运行机制,能够提供系统全面解决方案,具有良好信誉,有长期合作可能的企业作为PACS合作伙伴至关重要。同时,PACS系统的建设应遵循实用性、经济性、整体性、科学性、扩展性、一致性、可靠性、安全性等原则。

小结

总之,PACS与Internet相连应用于远程医疗,可充分发挥中心医院的指导作用,使多个地方的放射科医生或临床医生借助PSTN(公共交换电话网)、ISDN(综合业务数据网)、ATM(异步传输模式)同时观察分析同一图像,形成视讯会议,提高治疗水平、减少病人费用有直接作用;将PACS与HIS、RIS相连接,使临床科室特别是ICU医生通过计算机网络可快速方便地看到患者散在各个科室的文本和图像资料,及时制定处理方法、为治疗和抢救争取时间;更为重要的是可改变医院旧的影像管理模式,实现影像数字化、无胶片化,大大提高医院的医疗技术水平和工作效率,更好地为患者服务。

1 of 2 in the series: 专题新闻

21世纪医学最伟大的发明:PET-CT

PET-CT有什么好处。PET-CT在很多发达城市很受欢迎,在一些大型三甲医院已经引进了64排PET-CT,那么PET-CT有什么好处呢?

PET可以显示病灶病理生理特征,更易发现病灶;CT可以精确定位病灶,显示病灶结构变化。PETCT除了具备PET和CT各自的功能外,其独有的融合图像,将PET图像与CT图像融合,可以同时反映病灶的病理生理变化及形态结构变化,明显提高了诊断的准确性。

PET的作用是以代谢显像和定量分析为基础,应用组成人体主要元素的短命核素如11C、15O、13N和18F等正电子核素为示踪剂,不仅可快速获得多层面断层影象、三维定量结果以及三维全身扫描,而且还可以从分子水平动态观察到代谢物或药物在人体内的生理生化变化,用以研究人体生理、生化、化学递质、受体乃至基因改变。

PET-CT有什么好处:PET-CT则是将PET和CT(计算机体层显像)技术结合在一起,使用同一个检查床和同一个图像处理工作站,将PET图像和CT图像融合,可以同时放映肿瘤病灶的病理生理变化和形态结构,明显提高诊断的准确性。

PET-CT使用最成熟的是对全身肿瘤的评价。国外很多企业将派特CT检查作为一项福利, PET-CT目前是全球最高端的医学影像诊断设备。PET-CT的原理是:PET-CT是将派特和CT两个设备有机地结合在一起,使用同一个检查床和同一个图像处理工作站。派特CT同时具有派特和CT的功能,但它绝不是二者功能的简单叠加,因为派特与CT优势互补,1+1>2。派特可以显示病灶病理生理特征,更容易发现病灶; PET的全称为正电子发射计算机断层扫描。它是现在最先进的医学影像技术,它具有无创伤性的特点。

PET-CT的优点在上文已经有了介绍,PET-CT被誉为21世纪医学最伟大的发明。可以一次性查出全身的肿瘤,为肿瘤患者的早诊断提供的保障,因而现在好多人也选择PET-CT做防癌体检。

2 of 2 in the series: 专题新闻

Flutter环境更新方法

常规更新方法:

运行:flutter upgrade,然后等待自动更新完成即可,

非常贵更新方法:

1.更新flutter代码库

找到flutter库的安装目录,运行git,同步拉取到最新的代码,

2.更新依赖

运行flutter doctor -v 自动下载更新依赖的库
Microsoft Windows [版本 10.0.17134.112]
(c) 2018 Microsoft Corporation。保留所有权利。

F:\JavaWorker\deheng\android\hemodialysis>flutter doctor -v
Checking Dart SDK version...
Downloading Dart SDK from Flutter engine 72c7a7567228cdaf8b7aa4a9e3d212ef9d4cc0ed...
Unzipping Dart SDK...
Building flutter tool...
Running pub upgrade...
Downloading package sky_engine...                            1.1s
Downloading common tools...                                  2.6s
Downloading windows-x64 tools...                             5.9s
Downloading android-arm-profile/windows-x64 tools...         1.2s
Downloading android-arm-release/windows-x64 tools...         0.8s
Downloading android-arm64-profile/windows-x64 tools...       0.9s
Downloading android-arm64-release/windows-x64 tools...       0.9s
Downloading android-x86 tools...                             4.8s
Downloading android-x64 tools...                             4.9s
Downloading android-arm tools...                             3.4s
Downloading android-arm-profile tools...                     1.8s
Downloading android-arm-release tools...                     2.2s
Downloading android-arm64 tools...                           1.9s
Downloading android-arm64-profile tools...                   1.8s
Downloading android-arm64-release tools...                   1.5s
Downloading android-arm-dynamic-profile tools...             1.9s
Downloading android-arm-dynamic-release tools...             2.8s
Downloading android-arm64-dynamic-profile tools...           2.0s
Downloading android-arm64-dynamic-release tools...           1.7s
[√] Flutter (Channel beta, v0.10.3-pre.3, on Microsoft Windows [Version 10.0.17134.112], locale zh-CN)
    • Flutter version 0.10.3-pre.3 at F:\ProgramFiles\flutter
    • Framework revision 233435c02a (42 minutes ago), 2018-11-30 10:00:27 +0800
    • Engine revision 72c7a75672
    • Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

[√] Android toolchain - develop for Android devices (Android SDK 28.0.3)
    • Android SDK at F:\ProgramFiles\android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • ANDROID_HOME = F:\ProgramFiles\android\sdk
    • Java binary at: F:\ProgramFiles\android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)
    • All Android licenses accepted.

[√] Android Studio (version 3.2)
    • Android Studio at F:\ProgramFiles\android\Android Studio
    • Flutter plugin version 31.1.1
    • Dart plugin version 181.5656
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)

[√] IntelliJ IDEA Ultimate Edition (version 2018.2)
    • IntelliJ at F:\ProgramFiles\JetBrains\IntelliJ IDEA 2018.2.4
    • Flutter plugin version 30.0.2
    • Dart plugin version 182.5124

[√] Connected device (2 available)
    • MI PAD 4  • 6074f4a0     • android-arm64 • Android 8.1.0 (API 27)
    • Che1 CL20 • f4e3fb7f933b • android-arm   • Android 4.4.4 (API 19)

• No issues found!

F:\JavaWorker\deheng\android\hemodialysis>

4 of 7 in the series: Fltter移动开发相关