Why ?

合法性检查对于程序的健壮性具有重要作用。在Android开发中,良好的合法性检查设计机制可以使程序更加清晰,产生bug更少,交互更加友好。

What ?

合法性检查的目的在于确定边界。对于在程序中流动的数据来说,其流动路径往往是很复杂的。为了保证程序的健壮性,需要保证数据从一端流入并且从另外一端流出的过程中不会发生异常行为。数据流经的每一个方法都必须保证异常被正确处理。为了让每一个函数清晰简单,有必要在数据进入函数之前保证其合法性。让函数中的逻辑不受数据边界的影响。

Who ?

接受合法性检查的对象一般是某一事件触发后需要的初始数据,大多以函数参数形式进行调用。对于Android开发来说。最频繁需要进行检查的莫过于EditText组件。该组件接受用户的输入,是很多功能的数据来源。网络请求的返回数据也是很重要的数据来源。正确处理这些初始的数据,保证其合法性,使得之后的程序逻辑不再受数据异常的影响,同时给予用户一个良好的交互反馈是必须要做的。

When

合法性检查发生在数据中转的入口(也可能是运行的开始)。

How

合法性检查需要从以下几方面着手

  • 安全的类型转换工厂

由于程序的数据来源是很复杂的,数据往往需要进行加工和各种数据转换。虽然JAVA提供了许多数据转换的方法。但是,直接在功能代码中使用这些方法是不明智的。很可能产生异常,而当程序没有适当的捕捉和处理异常时,就有可能发生程序崩溃。安全的做法是建立一个安全的类型转换工厂,统一处理需要进行类型转换的数据。
举例:
假设用户输入两个数字,程序需要将两个数字加起来。直接进行类型转换是不安全的。
bad practice :

Double plus(String inputA, String inputB) {
    return Double.valueOf(inputA) + Double.valueOf(inputB);
}

good practice:

private Integer plus(String inputA, String inputB){
    Integer convertA = StringConverter.getInteger(inputA) ;
    Integer convertB = StringConverter.getInteger(inputB) ;
    if(convertA != null  &&  convertB != null) {
        return convertA  + convertB;
    }else {
         //null must be handled to avoid NullPointerException
        return null;
    }
}
public class StringConverter {
public static Integer getIntegerValue(String var) {
    try{
        return Integer.valueOf(var);
    }catch(Exception e) {
        //ignore much code of print exception and other options
        return null;
    }
}
} 
  • 安全的构造函数

在构造函数中检查初始化参数是一个很好的习惯,可以防止不恰当的初始化发生。
举例:

public class Age {
    int age;
    public Age(int age) throws AgeNegativeException {
    if(age == null || age < 0) {
        //age can never be a negative number or null
        throw(new AgeNegativeException());
    }else {
        this.age = age;
    }

    public int getAge() { return age;}
}
public class AgeNegativeException extends Exception {
    //exception definition details ignored
}
  • 分层清晰的异常处理机制

异常有可能发生在入口处,也有可能发生在运行时。数据流经的地方,都需要确定自己的边界。每一个函数都应该明确自己的责任。对于整个程序结构来说。针对各个不同的模块需要定义相关的异常并且在相应的层面上去处理异常。
举例:
结合上面两个例子,用户需要做一个年龄累加统计。每次输入两个需要累加的年龄,返回累加后的年龄。

public Age addAge(String inputA, String inputB) throws AgeNegativeException {
    //calculate and return
    return new Age(plus(inputA, inputB));
}

example1:

inputA = “dhkja”; inputB = "10";

如果用户输入了这两个值。那么

plus(inputA, inputB)

会返回一个null。在构造Age的时候就会抛出异常。由于这个异常是用户输入不当造成的因此需要将异常再次抛出到Activity那一层,让Activity提示用户输入有误。

  • 为每一个文本框设置校验
    为文本框设置校验涉及到两方面
    1、校验时间
    2、校验提示

校验时间:

  • 用户输入前
  • 用户输入时
  • 失去焦点时
  • 用户触发相关方法时
    前三种可以通过设置文本监听进行处理,最后一种属于事后检验不设置文本监听。

校验提示:

  • 弹出框形式
  • ErrorMessage
    弹出框可以弹出Toast或者一个dialog,ErrorMessage可以通过设置EditText 的ErrorMessage实现。也可以借助开源组件实现。例如android-edittext-validator

经过如此设计,就不太会受到数据异常的困扰了。关于文本监听和校验提示,会在另外文章说明。

Android开发中的输入合法性检验的更多相关文章

  1. java中的反射机制在Android开发中的用处

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...

  2. 关于Android开发中的证书和密钥等问题

    关于Android开发中的证书和密钥等问题 引言 除了Android发布应用签名时需要用到证书外,在进行google Map Api开发和Facebook SDK API开发等时都需要申请API Ke ...

  3. Android开发中,那些让您觉得相见恨晚的方法、类或接口

    Android开发中,那些让你觉得相见恨晚的方法.类或接口本篇文章内容提取自知乎Android开发中,有哪些让你觉得相见恨晚的方法.类或接口?,其实有一部是JAVA的,但是在android开发中也算常 ...

  4. android开发中的5种存储数据方式

    数据存储在开发中是使用最频繁的,根据不同的情况选择不同的存储数据方式对于提高开发效率很有帮助.下面笔者在主要介绍Android平台中实现数据存储的5种方式. 1.使用SharedPreferences ...

  5. Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令

    Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...

  6. 讨论Android开发中的MVC设计思想

    最近闲着没事,总是想想做点什么.在时间空余之时给大家说说MVC设计思想在Android开发中的运用吧! MVC设计思想在Android开发中一直都是一套比较好的设计思想.很多APP的设计都是使用这套方 ...

  7. Intent 对象在 Android 开发中的应用

    转自(http://www.ibm.com/developerworks/cn/opensource/os-cn-android-intent/) Android 是一个开放性移动开发平台,运行在该平 ...

  8. android开发中常犯的几个错误整理

    新手程序猿,在开发中难免会犯各种各样的错误,以下是整理的一些android开发中常见的错误,一起来看看吧. 1.避免将多个类放在一个文件夹里面,除非是一次性使用的内部类. 就是一个文件,最好给分它同名 ...

  9. Android开发中查看未root真机的app数据库

    在Android开发中,如果用到数据库来储存数据,那么难免就要查看数据库中的内容,可是对于未root的真机来说,查看数据库就不是那么容易了,如果仅仅为了查看数据库再把手机root了,有点得不偿失,所以 ...

随机推荐

  1. NUOJ 88

    思路1: 找规律,本题若是直接暴力搜索,就是f(n)=2^n-1,然后f(n)%1000000,那么结果会越界:所以考虑用f(n+1)=(2*f(n)+1)%1000000,不过遇到较大数据的时候,会 ...

  2. poj 2594 Treasure Exploration (二分匹配)

    Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 6558   Accepted: 2 ...

  3. 开发Android系统内置应用小记

    Android系统内置应用可以使用更多的API.更高的权限,与开发普通应用最大的差别在于编译,内置应用编译需要用到Android.mk文件.下面是我在开发过程中的一些小记. 1.在AndroidMai ...

  4. SQLite 命令

    在shell下直接敲 sqlite3  进入sqlite命令行模式下(CLP的shell模式,CLP是sqlite3的命令行程序) sqlite3 -help (注意有空格)显示命令行模式下,sqli ...

  5. 项目学习——电力系统底层架构ssh

    电力系统底层架构1.建立web工程 创建数据库 导入向对应的jar包2. 持久层: (1)在cn.itcast.elec.domain中创建持久化类ElecText @SuppressWarnings ...

  6. nyist 676 小明的求助

    http://acm.nyist.net/JudgeOnline/problem.php?pid=676 小明的求助 时间限制:2000 ms  |  内存限制:65535 KB 难度:2   描述 ...

  7. 《苹果开发之Cocoa编程》挑战1 创建委托 练习

    <苹果开发之Cocoa编程>第4版 P87 新建一个单窗口应用程序,设置某对象为窗口的委托,当用户调整窗口尺寸时,确保窗口高度为宽度的2倍. 需要实现的委托方法为:-(NSSize)win ...

  8. cursor变换

    cursor:hand 与 cursor:pointer 的效果是一样,都像手形光标.但用FireFox浏览时才注意到使用cursor:hand在FireFox.chorme里并被支持. cursor ...

  9. ZOJ2971 Give Me the Number 【模拟】

    这道题目使用Map. 然后一次性遍历下来即可. QAQ 注意初始化的时候小心点不要错.. Source Code: //#pragma comment(linker, "/STACK:167 ...

  10. cassandra 服务启动流程

    cassandra 服务启动流程 1.  setup 1)   CassandraDaemon ->main publicstaticvoidmain(String[]args) { insta ...