Flutter学习

常用网址

免费下载 !《AliFlutter 体系化建设和实践》
Flutter 开发文档
Flutter实战
Dart 编程语言概览
pub仓库
main函数使用了(=>)符号, 这是Dart中单行函数或方法的简写。

// =>是return语句的简写
add3(a, b) => a + b; 

变量以下划线(_)开头,在Dart语言中使用下划线前缀标识符,会强制其变成私有的。

Widget

Activity、Fragment、view 在Flutter中等价于Widget.

与Android view区别

  • Android中View是可变的,当用户交互或数据更新时,可直接调用View的invalidate方法重绘,达到更新UI的目的。
  • Flutter的widget是不可改变的因此不能直接更新,而必须使用Widget的状态。Flutter的widget分为有状态和无状态两种。它们的核心特性是相同的,每一帧它们都会重新构建,不同之处在于有状态的Widget有一个State对象,它可以跨帧存储状态数据并恢复它。

Stateless widgets 是不可变的, 这意味着它们的属性不能改变 ,所有的值都是最终的.
Stateful widgets(有状态的部件) 持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:

  1. 一个 StatefulWidget类。
  2. 一个 State 类。 StatefulWidget类本身是不变的,但是 State类在widget生命周期中始终存在.

stateful widget将自身的构建委托给State对象,State对象的build函数负责构建该Widget,当用户交互或数据发生变化时,Widget状态发生改变,调用State的 setState 方法通知它,而后State根据当前的状态信息,重新构建Widget tree

  • 在Android中,您可以从父级控件调用addChild或removeChild以动态添加或删除View。 在Flutter中,因为widget是不可变的,所以没有addChild。相反,您可以传入一个函数,该函数返回一个widget给父项,并通过 布尔值控制该widget的创建。
  • 在Flutter中,一个自定义widget通常是通过组合其它widget来实现的,而不是继承
  • 某些widget属性需要单个widget(child),而其它一些属性,如action,需要一组widgets(children),用方括号[]表示。

布局

Flutter中通过Row和Column来实现线性布局,类似于Android中的LinearLayout控件
row水平,Column竖直

  • 对于线性布局,有主轴和纵轴之分,如果布局是沿水平方向,那么主轴就是指水平方向,而纵轴即垂直方向;如果布局沿垂直方向,那么主轴就是指垂直方向,而纵轴就是水平方向。在线性布局中,有两个定义对齐方式的枚举类MainAxisAlignment和CrossAxisAlignment,分别代表主轴对齐和纵轴对齐。
  • mainAxisSize:表示Row在主轴(水平)方向占用的空间,默认是MainAxisSize.max,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度;
  • 而MainAxisSize.min表示尽可能少的占用水平空间,当子组件没有占满水平剩余空间,则Row的实际宽度等于所有子组件占用的的水平空间
  • textDirection:表示水平方向子组件的布局顺序(是从左往右还是从右往左),默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左)。
  • Row和Column都只会在主轴方向占用尽可能大的空间,而纵轴的长度则取决于他们最大子元素的长度
  • 如果Row里面嵌套Row,或者Column里面再嵌套Column,那么只有最外面的Row或Column会占用尽可能大的空间,里面Row或Column所占用的空间为实际大小

Stack类似FrameLayout很像,都是可以叠加的现实View
flutter中默认组件尺寸单位都是dp
double.infinity,可以使宽度占用尽可能多的空间

常用Widget和属性

  • Container:父view,宽高、背景色、圆角、margin
  • Padding:EdgeInsets.fromLTRB
  • Center:居中
  • TextField:输入框(TextEditingController)
  • Expanded:填充剩余布局,组件有个参数flex,可以实现比例分配。
    height如果不设置 界面显示会有问题,如果要设置,又不能准确的计算出结果,可以使用Expanded
  • BoxDecoration:圆角,需要放在Container里,实现边框、圆角、阴影、形状、渐变、背景图像
  • ShapeDecoration:实现四个边分别指定颜色和宽度、底部线、矩形边色、圆形边色、体育场(竖向椭圆)、 角形(八边角)边色
  • UnderlineTabindicator:下划线
  • EdgeInsets.only
  • Flutter 中官方提供CustomScrollView,让我们能够作何Appbar折叠的效果,并且很容易就能实现下拉刷新和加载更多。

点击

  • 在Flutter中,添加触摸监听器有两种方法:如果Widget支持事件监听,则可以将一个函数传递给它并进行处理。例如,RaisedButton有一个onPressed参数
  • 如果Widget不支持事件监听,则可以将该Widget包装到GestureDetector中,并将处理函数传递给onTap参数。
  • InkWell:点击

MaterialApp
MaterialApp是我们使用 Flutter开发中最常用的符合Material Design设计理念的入口Widget。你可以将它类比成为网页中的html标签,且它自带路由、主题色等功能。

Scaffold
Scaffold通常被用作MaterialApp的子Widget,它会填充可用空间,占据整个窗口或设备屏幕。Scaffold提供了大多数应用程序都应该具备的功能,例如顶部的appBar,底部的bottomNavigationBar,隐藏的侧边栏drawer等。

const Scaffold({
  Key key,
  this.appBar, // 标题栏
  this.body,  // 用于显示当前界面主要内容的Widget
  this.floatingActionButton, // 一个悬浮在body上的按钮,默认显示在右下角
  this.floatingActionButtonLocation, // 用于设置floatingActionButton显示的位置
  this.floatingActionButtonAnimator, // floatingActionButton移动到一个新的位置时的动画
  this.persistentFooterButtons, // 多状态按钮
  this.drawer, // 左侧的抽屉菜单
  this.endDrawer, //  右'侧的抽屉菜单
  this.bottomNavigationBar,// 底部导航栏。
  this.bottomSheet, // 显示在底部的工具栏
  this.backgroundColor,// 内容的背景颜色
  this.resizeToAvoidBottomPadding = true, // 控制界面内容 body 是否重新布局来避免底部被覆盖,比如当键盘显示的时候,重新布局避免被键盘盖住内容。
  this.primary = true,// Scaffold是否显示在页面的顶部
}) 

AppBar属性
leading 返回键
iconTheme Appbar 上图标的颜色、透明度、和尺寸信息。默认值为 ThemeData.primaryIconTheme
centerTitle 标题是否居中显示,默认值根据不同的操作系统,显示方式不一样。
Flutter AppBar(顶端栏)

Button
RaisedButton :凸起的按钮,其实就是Android中的Material Design风格的Button ,继承自MaterialButton
FlatButton :扁平化的按钮,继承自MaterialButton
OutlineButton :带边框的按钮,继承自MaterialButton
IconButton :图标按钮,继承自StatelessWidget

SizedBox

  • 一般是用来限制孩子控件的大小。
  • 还有这么一种场景也可以使用SizeBox,就是可以代替padding和container,然后 用来设置两个控件之间的间距,比如在行或列中就可以设置两个控件之间的间距 主要是可以比使用一个padding或者container简单方便 (在Flutter中可能用不同的控件可以实现到相同的目的,尽量使用越简单的widget来实现)
  • 控件在整个手机屏幕中间对齐:ConstrainedBox、SizedBox、Center

banner+list三种实现方式
listView  
CustomScrollView 
ScrollView

debugPrint('classList-' + classList.toString());

Intents

Navigator.push跳页面

  • 在Android中,Intents主要有两种使用场景:在Activity之间切换,以及调用外部组件。 Flutter不具有Intents的概念,但如果需要的话,Flutter可以通过Native整合来触发Intents。
  • 要在Flutter中切换屏幕,您可以访问路由以绘制新的Widget。 管理多个屏幕有两个核心概念和类:Route 和 Navigator。Route是应用程序的“屏幕”或“页面”的抽象(可以认为是Activity), Navigator是管理Route的Widget。Navigator可以通过push和pop route以实现页面切换。
  • 在Flutter中,导航器管理应用程序的路由栈。将路由推入(push)到导航器的栈中,将会显示更新为该路由页面。 从导航器的栈中弹出(pop)路由,将显示返回到前一个路由。
    Flutter路由&pop()&Push()全面解析

异步

  • flutter没有UI线程,也没有子线程。也就是说,无论是网络请求,数据处理,页面渲染,都是在同一个线程里面,那怎么保障页面渲染不会anr呢?
  • Dart是一个单线程的语言,遇到有延迟的运算(比如IO操作、延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到卡顿,于是通常用异步处理来解决这个问题。当遇到有需要延迟的运算(async)时,将其放入到延迟运算的队列(await)中去,把不需要延迟运算的部分先执行掉,最后再来处理延迟运算的部分。( 延迟队列)
  • 在Flutter可以利用多个CPU内核来执行耗时或计算密集型任务。这是通过使用Isolates来完成的。是一个独立的执行线程,它运行时不会与主线程共享任何内存。这意味着你不能从该线程访问变量或通过调用setState来更新你的UI
    聊一聊Flutter Engine线程管理与Dart Isolate机制
    异步async、await和Future的使用技巧

我们需要用到 async,await,Future 三兄弟来进行处理。
async ,它是一个延迟计算的标志,标志了把这个任务放到了延迟运算的队列(await)中,通过Future进行返回。

比如说我们的网络请求:

//  post请求
  static Future<Map> post(String url,
      {Map<String, String> params, bool saveCookie = false}) async {
    if (params == null) {
      params = new Map();
    }
    String _url = Api.BASE_URL + url;
    if (OsApplication.cookie != null) {
      params['Cookie'] = OsApplication.cookie;
    }
    http.Response res = await http.post(_url, body: params);
    return _dealWithRes(res, saveCookie: saveCookie);
  }

在Dart中,有await标记的运算,其结果值都是一个Future对象,Future不是String类型
Dart规定有async标记的函数,只能由await来调用,比如这样:
String data = await getData();

 //get请求,请求返回值为Future<String>类型,即其返回值未来是一个String类型的值
  getData() async {    
     //async关键字声明该函数内部有代码需要延迟执行
    return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"}); //await关键字声明运算为延迟执行,然后return运算结果
  }

then
await会阻塞流程,等待紧跟着的的Future执行完毕之后,再执行下一条语句,而如果用了Future.then这个api,那么就不会等待,直接执行下面的语句,等Future执行完了,再调用then这个方法。

自动生成实体类

dynamic ,var、object

dynamic
所有dart 对象的基础类型,在大多数情况下,不直接使用它 通过它定义的变量会关闭类型检查,这意味着 dynamix x= ‘hal’; x.foo();这段静态类型检查不会报错,但是运行时会crash,因为x 并没有foo() 方法,所以建议大家在编程时不要直接使用dynamic;
var
是一个关键字,意思是"我不关心这里的类型是什么",系统会自动判断类型 runtimeType;
object
是Dart 对象的基类,当你定义: object o =xxx ;时这个时候系统会认为o是个对象,你可以调用o的toString()和hashCode()方法因为Object 提供了这些方法,但是如果你尝试调用o.foo()时,静态类型检查会运行报错。综上不难看出dynamic 与object 的最大的区别是在静态类型检查上。

MethodChannel与原生交互

将 Flutter 集成到现有应用
Flutter 与 Android 的相互通信

File > New > New Module > flutter 新建到自己项目目录下

可以从Native层调用flutter层的dart代码,也可以在flutter层调用Native的代码,而作为通讯桥梁就是MethodChannel,这个类在初始化的时候需要注册一个渠道值。这个值必须是唯一的,并且在使用到的Native层和Flutter层互相对应。
flutter调用Android
注册

static const nativeChannel =
      const MethodChannel('com.example.flutter/native');

flutter

      Map<String, dynamic> result = {'message': '我从Flutter页面回来了'};
                    nativeChannel.invokeMethod('goBackWithResult', result);

Android

 MethodChannel nativeChannel = new MethodChannel(flutterEngine.getDartExecutor(), CHANNEL_NATIVE);
        nativeChannel.setMethodCallHandler((methodCall, result) -> {
            switch (methodCall.method) {
                //回调
            case "goBackWithResult":
                    // 返回上一页,携带数据
                    ActivityManager.getInstance().finishActivity(FlutterActivity.class);
                    Toast.makeText(this, (String) methodCall.argument("message"), Toast.LENGTH_SHORT).show();
                    break;
                case "getSendParams":
                    result.success(getSendParams());
                    break;
                default:
                    result.notImplemented();
                    break;
            }
        });

异步

 Future getSendParams() async {
    String params = await _SendFeedBackState.nativeChannel
        .invokeMethod('getSendParams', "");
    print("getSendParams:" + params);
  }

Android调用flutter
Android

        Map<String, Object> result = new HashMap<>();
        result.put("message", message);
        // 创建MethodChannel
        MethodChannel flutterChannel = new MethodChannel(flutterEngine.getDartExecutor(), CHANNEL_FLUTTER);
        flutterChannel.invokeMethod("onActivityResult", result);

flutter

  @override
  void initState() {
    super.initState();
    Future<dynamic> handler(MethodCall call) async {
      switch (call.method) {
        case 'onActivityResult':
          Fluttertoast.showToast(
            msg: call.arguments['message'],
            toastLength: Toast.LENGTH_SHORT,
          );
          break;
        case 'goBack':
          // 返回上一页
          if (Navigator.canPop(context)) {
            Navigator.of(context).pop();
          } else {
            nativeChannel.invokeMethod('goBack');
          }
          break;
      }
    }

    flutterChannel.setMethodCallHandler(handler);
  }

其他

使用 ‘尾随逗号’
Flutter中如何使用原生控件或组件
Flutter代码通常涉及构建相当深的树状数据结构,例如在一个build方法中。 为了获得良好的自动格式化,我们建议您采用可选的尾部逗号。添加尾随逗号很简单:始终在函数、方法和构造函数的参数列表末尾添加尾随逗号,以便保留您的编码格式。 这将有助于自动格式化程序为Flutter样式代码插入适当的换行符。

Eventbus

监听特定的

eventeventBus.on<UserLoggedInEvent>().listen((event) {
  print(event.user);});

监听所有的

eventeventBus.on().listen((event) {
  print(event. runtimeType);});

发送一个

eventeventBus.fire(new UserLoggedInEvent(myUser));

写text先写padding

  child: new Padding(
                      padding: new EdgeInsets.all(10.0),
                      child: new Text(
                        '马上登录',
                        style:
                            new TextStyle(color: Colors.white, fontSize: 16.0),
                      ),
                    )),
本文转载于网络 如有侵权请联系删除

相关文章

  • 神经网络学习

    发展1958年,计算科学家Rosenblatt提出了由两层神经元组成的神经网络,并将之命名为“感知器”(Perceptron)。 感知器有两个层次:输入层和输出层。 输入层里的“输入单元”只负责传输数据,不做计算。 输出层里的“输出单元”则需要对前面一层的输入进行计算。 感知器是当时首个可以学习的人工神经网络。Rosenblatt现场演示了其学习识别简单图像的过程。 按照不同的连接方式,神经网络可以分为:感知器模型多层感知机模型前向多层神经网络Hopfield神经网络动态反馈网络自组织神经网络等。1986年,Rumelhar和Hinton等人提出了反向传播(BackPropagation,BP)算法,解决了两层神经网络所需要的复杂计算量问题,从而带动了使用两层神经网络研究的热潮。 两层神经网络除了包含一个输入层,一个输出层以外,还增加了一个中间层。 中间层和输出层都是计算层。 理论证明,两层神经网络可以无限逼近任意连续函数。 面对复杂的非线性分类任务,带一个隐藏层的两层神经网络可以取得很好的分类结果。 2006年,Hinton在《Science》和相关期刊上发表了论文,首次提出了“深度

  • 【DB笔试面试762】在Oracle中,DG中常常用到的比较有用的性能视图有哪些?

    ♣题目部分在Oracle中,DG中常常用到的比较有用的性能视图有哪些?♣答案部分 lV$MANAGED_STANDBY:包含与物理备库相关的数据库进程(例如:LGWR、RFS、LNS、ARCH、MRP等)的信息。lV$ARCHIVED_LOG:在备库执行此查询时,显示该备库接收到的日志。lV$LOG_HISTORY:包含归档历史的详细信息。lV$DATAGUARD_STATUS:包含DG生成的消息,这些消息被写入该特定数据库(主库或备库)的告警日志或跟踪文件中。lV$RECOVERY_PROGRESS:包含与备库恢复相关的统计信息。lV$STANDBY_EVENT_HISTOGRAM:包含某个物理备库的应用滞后的直方图。lDBA_LOGSTDBY_LOG:包含关于已经被或正在被SQLApply处理的归档日志的信息。lDBA_LOGSTDBY_EVENTS:包含最近的SQLApply事件(例如异常终止)的记录,这些事件也存在于运行SQLApply的数据库实例的告警日志中。lV$LOGSTDBY_PROCESS:包含每个SQLApply进程的当前状态。本文选自《Oracle程序员面试笔试宝

  • Phpstorm通过FTP上传到远程服务器同步开发

    背景其实大多数时候我们都是在本地开发、测试,等项目基本完成后才会部署到线上服务器,但总有那么一些情况我们需要在线上服务器开发部署测试。比如:开发微信公众号后台等这个你要问我为什么需要线上才能开发微信公众号,因为微信需要从服务器获取数据才能返回给用户而微信有无法访问你的本地服务器。所以只能线上开发。Phpstorm中FTP上传所以我们需要一种方法将程序实时上传到线上服务器进行测试开发。而FTP是一种较好且普遍的方法。配置找到Tools|Deployment|Configuration点击新建一个FTP输入名称输入FTP信息点击测试链接如下,基本配置就完成了。但还没完 设置Mappings如上图,需要设置Mappings下面的Deploymentpath,不要是不能上传文件的,会出问题!!!这点尤其重要。 启用自动上传路径:Tools|Deployment|AutomaticUpload(always)这样,当你保存文件时,就会自动上传啦!说明项目有一些基础文件【比如框架自带的一些文件】还没上传到服务器呢,也不会自动上传到服务器,怎么弄呢?全选文件,右击上传这样就会全部上传到远程服务器啦!

  • 聊聊nacos config的publishConfig

    序本文主要研究一下nacosconfig的publishConfigConfigControllernacos-1.1.3/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java@Controller @RequestMapping(Constants.CONFIG_CONTROLLER_PATH) publicclassConfigController{ ​ privatestaticfinalLoggerlog=LoggerFactory.getLogger(ConfigController.class); ​ privatestaticfinalStringNAMESPACE_PUBLIC_KEY="public"; ​ publicstaticfinalStringEXPORT_CONFIG_FILE_NAME="nacos_config_export_"; ​ publicstaticfinalStringEXPORT_C

  • 初识Python3

    Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。由GuidovanRossum于1989年底发明,第一个公开发行版发行于1991年。 简介Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。由GuidovanRossum于1989年底发明,第一个公开发行版发行于1991年。像Perl语言一样,Python源代码同样遵循GPL(GNUGeneralPublicLicense)协议。Python的3.0版本,常被称为Python3000,或简称Py3k。相对于Python的早期版本,这是一个较大的升级。环境安装配置,请参考基础服务系列-Centos7安装Anaconda本文记录初识Python3中的点点滴滴。入门一般情况下,熟悉一门编程语言的话,对比着学习另外一种会轻松很多。Python的特点是,入门容易,精通难。基础的语法、数据类型,参考Python3基础语法语法练习,可以使用在线笔记Jupyter。也可以直接注册一些在线的。阿里云天池:阿里大数据平台,会有一些比赛、数据集、AI学习路线图。Azurenotebook:微软提供的在线Jupyter服务。

  • restapi(1)- 文件上传下载服务

    上次对restapi开了个头,设计了一个包括了身份验证和使用权限的restful服务开发框架。这是一个通用框架,开发人员只要直接往里面加新功能就行了。虽然这次的restapi是围绕着数据库表的CRUD操作设计的,但文件类数据在服务端与客户端之间的交换其实也很常用,特别是多媒体类如图片等文件类型。那我们就试着设计一个文件交换服务功能然后看看能不能很方便的加入到restapi框架内。akka-http是以akka-stream为核心的,使用了大量的akka-stream功能。akka-stream中有一个FileIO组件库,里面提供了一系列有关文件读写功能,以数据流Source,Sink方式呈现:... deffromPath(f:Path,chunkSize:Int=8192):Source[ByteString,Future[IOResult]]= fromPath(f,chunkSize,startPosition=0) ... deftoPath( f:Path, options:Set[OpenOption]=Set(WRITE,TRUNCATE_EXISTING,CREATE)

  • for死循环、怪异字符串、两次return……Python冷知识(三)

    本文转载自Python编程时光(ID:Python-Time)冷知识系列,已经更新至第三篇。前两篇传送门小明给你准备好了,还没阅读的可以学习一下。谈谈Python那些不为人知的冷知识(一) 谈谈Python那些不为人知的冷知识(二)for死循环for循环可以说是基础得不能再基础的知识点了。但是如果让你用for写一个死循环,你会写吗?这是个开放性的问题,在往下看之前,建议你先尝试自己思考,你会如何解答。好了,如果你还没有思路,那就来看一下一个海外MIT群友的回答:foriiniter(int,1):pass复制是不是懵逼了。iter还有这种用法?这为啥是个死循环?这真的是个冷知识,关于这个知识点,你如果看中文网站,可能找不到相关资料。还好你可以通过IDE看py源码里的注释内容,介绍了很详细的使用方法。原来iter有两种使用方法,通常我们的认知是第一种,将一个列表转化为一个迭代器。而第二种方法,他接收一个callable对象,和一个sentinel参数。第一个对象会一直运行,直到它返回sentinel值才结束。那int呢,这又是一个知识点,int是一个内建方法。通过看注释,可以看出它是有默

  • split分割文件

    以指定大小分割split-b100M[文件][分割文件名头] 以行数分割split-l100[文件][分割文件名头] 合并cat[分割文件名头*]>[文件]

  • 第一章:1-11、在上题的分组交换网中,设报文长度和分组长度分别为x和(p+h)(bit),其中p为分组的数据部分的长度,而h为每个分组所带的控制信息固定长度,与p的大小无关。通信的两端共经过k段链路。链路的数据率为b(bit/s),但传播时延和结点的排队时间均可忽略不计。若打算使总的时延为最小,问分组的数据部分长度p应取为多大?

    《计算机网络》谢希仁著第四版课后习题答案答: 分组个x/p, 传输的总比特数:(p+h)x/p 源发送时延:(p+h)x/pb 最后一个分组经过k-1个分组交换机的转发,中间发送时延:(k-1)(p+h)/b 总发送时延D=源发送时延+中间发送时延          D=(p+h)x/pb+(k-1)(p+h)/b 令其对p的导数等于0,求极值         p=√hx/(k-1)

  • 解决:用PivotGridControl 与 chartControl 配合使用,Series最大只显示10条

    修改 PivotGridControl  控件的 OptionsChartDataSource.MaxAllowedSeriesCount 的值就可以了  默认为10条

  • 怎么样加快JavaScript加载和执行效率

    概览 无论当前JavaScript代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成。JavaScript执行过程耗时越久,浏览器等待响应用户输入的时间就越长。浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或JavaScript的命名空间,它们对后面页面内容造成影响。一个典型的例子就是在页面中使用document.write()。 JavaScript代码内嵌示例 <html> <head> <title>SourceExample</title> </head> <body> <p> <scripttype="text/javascript"> document.write("Todayis"+(newDate()).toDateString()); </script> </p> </body> </html> 复制   当浏览器遇到<script>标签时,当前html页面无从获

  • 面试题44:扑克牌的顺子

    题目描述 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。 题目分析 剑指Offer(纪念版)P227 代码实现 boolIsContinuous(int*numbers,intlength) { if(numbers==NULL||length<1) returnfalse; qsort(numbers,length,sizeof(int),compare); intnumberOfZero=0; intnumberOfGap=0; //统计数组中0的个数 for(inti=0;i<length&&numbers[i]==0;++i) ++numberOfZero; //统计数组中的间隔数目 intsmall=numberOfZero; intbig=small+1; while(big<length) { //两个数相等,有对子,不可能是顺子 if(numbers[small]==numbers[big]) returnfalse;

  • 站在产品经理的角度看问题

    如果我们站在另外一个角度看太阳,往往会看到他身边还有许多星星。。。。。。 很多产品经理谈到需求评审可能都闻风色变,因为总是被虐的不要不要的,就像荒野猎人里被熊虐的小李子;但是,依然有那么些产品经理对需求评审会情有独钟,难得有个机会和各路大侠比试切磋,享受这舌战群雄的快感。前方高能预警,文章稍长,建议产品新人耐心认真读完,高手求拍砖或自行闭目,阿门~ 什么是需求评审? 需求评审是产品进入正式开发之前非常重要的一环,只有所有人都认为需求已经没有什么可挑剔了评审才能通过,所以需求评审也是一个“鸡蛋里挑骨头”的过程。产品经理在这场「辩论」过程中,需要不断有效的展示自己的观点,以便获得更多的认可,最终号召大家(乐意)一起往一个产品目标努力奋斗。 为什么要需求评审? 让与会者清晰的了解需求是什么,需求从哪里来,对现有业务有什么影响,预期收益是什么; 让技术及测试对产品方案有详细的了解,以便后续开发更高效,没有谁愿意在后续的编写测试用例及开发阶段再去反复沟通确认,毕竟那是非常低效的做法,当然,特殊情况除外; 让与会者清晰的知道自己在整个方案落地过程中处于什么位置,职责是什么,需要做什么,准备

  • C#把Xml转换为DataSet的两种方法

    转:http://blog.csdn.net/beyondqd/article/details/6724676 下面给出两个实现XML数据转成DataSet的两个方法。第1种://通过传入的特定XML字符串,通过ReadXml函数读取到DataSet中。protectedstaticDataSetGetDataSetByXml(stringxmlData){          try          {              DataSetds=newDataSet();               

  • javascript变量声明提升

    javascript变量声明提升(hoisting)   javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。 先看一段代码 1 2 3 4 5 varv="hello"; (function(){   console.log(v);   varv="world"; })(); 这段代码运行的结果是什么呢?答案是:undefined这段代码说明了两个问题,第一,function作用域里的变量v遮盖了上层作用域变量v。代码做少些变动 1 2 3 4 5 varv="hello"; if(true){   console.log(v);   varv="world"; } 输出结果为"hello",说明javascript是没有块级作用域的。函数是JavaScript中唯一拥有自身作用域的结构。 第二,在functio

  • cucumber系列(四) RubyGems下载源更新的问题

    1,Rubygem类似于Java里maven的角色,就是一个库管理工具,可以远程下载和安装Ruby库。   1,gemsources-l#查看gem安装时的下载源在哪里,比如我本机的是http://xxxxrepo:3030/,一个无效的地址,所以我试图install工具时总会报错。 2,gemsources--removehttp://xxxxrepo:3030/#remove掉这个原来的下载地址。 3,gemsources-ahttp://ruby.taobao.org/#更新下载源地址为淘宝的镜像http://ruby.taobao.org/,也可以更新为http://rubygems.org/,但由于有被墙的风险和速度考虑,我选择淘宝的镜像。#请确保只有一个源ruby.taobao.org 4,gemsources-l #查看一下当前的下载源为http://ruby.taobao.org/。 5,geminstallrails#安装rails.复制    2,http://ruby-china.org 是一个好网站,

  • Oracle命令--删除归档日志

    oracle@linux144:~/db/oradata/archlog>l total22185212 drwxr-xr-x2oracleoinstall    122882012-11-2809:31./ drwxr-xr-x3oracleoinstall     40962012-09-1914:59../ -rw-r-----1oracleoinstall2863959042012-09-2708:10archivelog_1_100_787665209.log -rw-r-----1oracleoinstall2866826242012-09-2715:01archivelog_1_101_787665209.log -rw-r-----1oracleoinstall2866933762012-09-2800:17archivelog_1_102_787665209.log -rw-r-----1oracleoinstall2864348162012-09-2814:57archi

  • FreeMarker基础语法,宏,引用 等

    FreeMarker的插值有如下两种类型: 1,通用插值${expr}; 2,数字格式化插值:#{expr}或#{expr;format} ${book.name?if_exists}//用于判断如果存在,就输出这个值 ${book.name?default(‘xxx’)}//默认值xxx ${book.name!"xxx"}//默认值xxx ${book.date?string('yyyy-MM-dd')}//日期格式  ${book?string.number}20//三种不同的数字格式 ${book?string.currency}--<#--$20.00--> ${book?string.percent}—<#--20%--> <#assignfoo=ture/>//声明变量,插入布尔值进行显示 ${foo?string("yes","no")}<#--yes-->   大小比较符号使用需要注意:(xml的原因),可以用于比较数字和日期&nb

  • why OpenCV is slower than Matlab in matrix related operation,如:特征值分解,奇异值分解

    OpenCVisnotdesignedforsolvingmatrixrelatedoperationlike:multiplication,eigenvaluedecompositionorSVD,etc.,soyourresultisnotsurprisetome.Foryourproblem,theretwokindsofchoice:thefirstchoiceisusingadedicatedlibrary,lapackorEigenisrecommended,thesecondoneisusingawrappedlibrary,suchasArmadilloorCVMlib.Ihavetestedallofthem,oryoucanseemoreatthis,andmychoiceislapack,whichgivesthefastestspeed(onWindows,withVSIDE).Hopethishelp. 2. Thiskindofquestionisrecurringandshouldbeansweredmoreclearlythan“Matlabuse

  • mybatis动态sql和缓存

    搭建环境和前面的基本一样,主要是配置mapper接口,mapperXml文件,mybaits核心配置文件,测试类有不同的地方 1.mapper接口 packagemapper; importpojo.User; importjava.util.HashMap; importjava.util.List; importjava.util.Map; publicinterfaceUserMapper{ publicList<User>getUserList(); publicList<User>getUserList2(); publicList<User>getUserLisIf(HashMap<String,Object>map); }复制   2.mapperXml文件 <?xmlversion="1.0"encoding="UTF-8"?> <!DOCTYPEmapper PUBLIC"-//mybatis.org//DTDMapper3.0//EN" "http://mybatis.org/

  • 第十二周作业

    1.编写一个程序,实现字符串大小写的转换并倒序输出。要求如下(1)使用for循环将字符串“ Hello world”从最后一个字符开始遍历(2)遍历的当前字符如果是大写字符,就使用 toLower Case()方法将其转换为小写字符,反之则使用 toUpper Case()方法将其转换为大写字符。(3)定义一个 StringBuffer对象,调用 append(方法依次添加遍历的字符,最后调用String Buffer对象的 toString(方法,并将得到的结果输出。 packageaaa; publicclasssss{ publicstaticvoidmain(String[]args){ //TODO自动生成的方法存根 Strings="HelloWorld"; char[]c=s.toCharArray(); StringBufferbuffer=newStringBuffer(); for(inti=s.length()-1;i>=0;i--){ if((c[i]

相关推荐

推荐阅读