Android開發(fā)思考之內(nèi)容檢查代碼優(yōu)化

前言

平時(shí)我們寫代碼比如登錄注冊(cè),在調(diào)接口之前肯定要檢查手機(jī)號(hào)啊晕粪,密碼啊是否規(guī)范挤悉,本文稱為內(nèi)容檢查。大多數(shù)人可能就是用if判斷一大串巫湘,我也是装悲,但是現(xiàn)在很煩,很low尚氛,所以想優(yōu)化一下這種代碼诀诊。

mDataBing.btnRegister.setOnClickListener(v -> {

            String phoneNum = mDataBing.edtPhone.getText().toString().trim();
            String password = mDataBing.edtPassword.getText().toString().trim();

            if (TextUtils.isEmpty(phoneNum)) {
                toast("手機(jī)號(hào)不能為空");
                return;
            }

            if (RegexUtils.isMobileExact(phoneNum)) {
                toast("手機(jī)號(hào)不正確");
                return;
            }

            if (TextUtils.isEmpty(password)) {
                toast("密碼不能為空");
                return;
            }

            if (password.length() < 6) {
                toast("密碼不能少于6位");
                return;
            }

            //注冊(cè)
            register();

        });

有的app非空可能不會(huì)檢查,而是當(dāng)輸入內(nèi)容為空時(shí)讓提交按鈕不可點(diǎn)擊阅嘶。也就是當(dāng)所有的EditText有內(nèi)容時(shí)属瓣,按鈕才可點(diǎn)擊。我也寫了個(gè)工具類:

/**
 *
 * @author XuNeverMore
 * @QQ 1045530120
 * @create on 2018/2/2 0002
 * @github https://github.com/XuNeverMore
 */

public class SubmitUtil implements TextWatcher {


    private Button btnSubmit;//提交按鈕
    private EditText[] editTexts;//需要填寫內(nèi)容的輸入框


    private SubmitUtil() {

    }

    public SubmitUtil(Button btnSubmit, EditText... editTexts) {
        this.btnSubmit = btnSubmit;
        this.editTexts = editTexts;
    }


    public static SubmitUtil newInstance(){
        return new SubmitUtil();
    }

    public SubmitUtil setSubmitBtn(Button btnSubmit){
        this.btnSubmit = btnSubmit;
        return this;
    }

    public SubmitUtil setEditTexts(EditText... editTexts){
        this.editTexts = editTexts;
        return this;
    }

    /**
     * 同步操作
     */
    public SubmitUtil syncOperations(){
        for(EditText e:editTexts){
            e.addTextChangedListener(this);
        }
        checkState();
        return this;
    }



    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        checkState();
    }

    private void checkState() {
        boolean notEmpty = isAllEditTextNotEmpty();
        btnSubmit.setEnabled(notEmpty);
    }

    /**
     * 所有EditText輸入內(nèi)容均非空
     * @return
     */
    private boolean isAllEditTextNotEmpty() {

        for(EditText e:editTexts){
            if(TextUtils.isEmpty(e.getText().toString().trim())){
                return false;
            }
        }

        return true;
    }

    @Override
    public void afterTextChanged(Editable s) {

    }
}

首先看下圖讯柔,基本的流程抡蛙。之前寫博客沒畫過流程圖,隨便找了個(gè)軟件畫了下魂迄。流程圖是不是這樣畫的粗截,我不知道,意思大概就是這樣:


map.png

這樣思路清晰點(diǎn)极祸,主要工作就是我要寫一個(gè)工具類慈格,可以檢查多個(gè)條件,并且這些條件是可以配置的(比如你要辣椒不要醋遥金,我要醋不要蔥浴捆,他全都要,干擾你哈哈)稿械。當(dāng)一個(gè)條件不滿足時(shí)需要進(jìn)行相應(yīng)的提示选泻,并返回結(jié)果false;當(dāng)所有結(jié)果都滿足時(shí),返回結(jié)果true;思考清楚了美莫,代碼真是呼之欲出页眯。

大概設(shè)計(jì)了下接口如下:

/**
 * 
 * @author XuNeverMore
 * @QQ 1045530120
 * @create on 2018/2/2 0002
 * @github https://github.com/XuNeverMore
 */

public interface IContentChecker {


    /**
     * 檢查條件
     */
    public interface Condition{
        /**
         * 是否符合條件
         * @param body
         * @return
         */
        boolean match(Body body);

        void showTips(Body body);

    }


    /**
     * 被檢查的內(nèi)容
     */
    public interface Body{

        /**
         * 被檢查內(nèi)容的名字
         * @return
         */
        CharSequence getName();

        /**
         * 被檢查的具體內(nèi)容
         * @return
         */
        CharSequence getContent();

    }

    boolean check(Body body, List<Condition>conditions);

}

OK,下面就是具體的實(shí)現(xiàn)了,為了簡(jiǎn)單易用那肯定要支持鏈?zhǔn)秸{(diào)用厢呵。

ContentBody(檢查內(nèi)容實(shí)現(xiàn)類)

public class ContentBody implements IContentChecker.Body {

    private String name;
    private String content;

    public ContentBody(String name, String content) {
        this.name = name;
        this.content = content;
    }

    @Override
    public CharSequence getName() {
        return name;
    }

    @Override
    public CharSequence getContent() {
        return content;
    }
}


BaseCondition 具體的條件自己去實(shí)現(xiàn)

public abstract class BaseCondition implements IContentChecker.Condition {



    @Override
    public void showTips(IContentChecker.Body body) {

    }
}

內(nèi)容檢查器窝撵,初步。

ContentChecker

/**
 * 內(nèi)容檢查工具類
 *
 * @author XuNeverMore
 * @QQ 1045530120
 * @create on 2018/2/2 0002
 * @github https://github.com/XuNeverMore
 */

public class ContentChecker implements IContentChecker {

    private ContentChecker() {

    }


    private Body body;
    private List<Condition> conditionList;

    private ContentChecker(Body body) {
        this.body = body;
    }

    public static ContentChecker getChecker(Body body){

        return new ContentChecker(body);
    }

    /**
     * 添加條件
     * @param condition
     * @return
     */
    public ContentChecker addCondition(Condition condition){
        if(conditionList == null){
            conditionList = new ArrayList<>();
        }
        conditionList.add(condition);

        return this;
    }

/**
     * 檢查條件并返回檢查結(jié)果
     * @return
     */
    public boolean getCheckResult(){

        if(this.body == null||this.conditionList==null){
            throw new NullPointerException("檢查內(nèi)容和條件不能為空");
        }

        return check(this.body,this.conditionList);
    }


    @Override
    public boolean check(@NonNull Body body, @NonNull List<Condition> conditions) {

        for (Condition c : conditions) {
            if (!c.match(body)) {
                c.showTips(body);
                return false;
            }
        }
        return true;
    }


}

用法

簡(jiǎn)單的一個(gè)例子判斷手機(jī)號(hào)不能空并且符合手機(jī)號(hào)規(guī)則的襟铭。

ContentBody phoneNumBody = new ContentBody("手機(jī)號(hào)", phoneNum);
boolean checkResult = ContentChecker.getChecker(phoneNumBody)
                    .addCondition(new BaseCondition() {
                        @Override
                        public boolean match(IContentChecker.Body body) {

                            return RegexUtils.isMobileExact(phoneNum);
                        }

                        @Override
                        public void showTips(IContentChecker.Body body) {
                            ToastUtils.showShort(body.getName() + "不正確碌奉!");
                        }
                    })
                    .addCondition(new BaseCondition() {
                        @Override
                        public boolean match(IContentChecker.Body body) {
                            return TextUtils.isEmpty(body.getContent());
                        }

                        @Override
                        public void showTips(IContentChecker.Body body) {
                            ToastUtils.showShort(body.getName()+"手機(jī)號(hào)不能為空");
                        }
                    })
                    .getCheckResult();

自我感覺看起來還不錯(cuò)鏈?zhǔn)秸{(diào)用短曾,結(jié)構(gòu)清晰,比if判斷好些赐劣。每個(gè)條件每次得實(shí)現(xiàn)還是比較繁瑣嫉拐,我們可以把常用的都實(shí)現(xiàn)了,然后用的時(shí)候直接new就行了魁兼。下面是用實(shí)現(xiàn)過了條件類寫的婉徘,更簡(jiǎn)單明了。條件有必要的話可以用單例模式搞出來咐汞。

 ContentBody phoneNumBody = new ContentBody("手機(jī)號(hào)", phoneNum);

            boolean checkResult = ContentChecker.getChecker(phoneNumBody)
                    .addCondition(new NonNullCondition())
                    .addCondition(new PhoneNumCondition())
                    .getCheckResult();

現(xiàn)在基本上解決了用if檢查的繁瑣了盖呼,還有一個(gè)問題就是檢查多個(gè)的內(nèi)容需要一點(diǎn)點(diǎn)優(yōu)化。所以我寫了一個(gè)內(nèi)部?jī)?nèi)來解決多個(gè)內(nèi)容檢查的問題碉考。

ContentChecker.Machine 用于多項(xiàng)內(nèi)容檢查

public class ContentChecker implements IContentChecker {

    private ContentChecker() {

    }

    private Body body;
    private List<Condition> conditionList;

    private ContentChecker(Body body) {
        this.body = body;
    }

    public static ContentChecker getChecker(Body body){

        return new ContentChecker(body);
    }

    public ContentChecker addCondition(Condition condition){
        if(conditionList == null){
            conditionList = new ArrayList<>();
        }
        conditionList.add(condition);

        return this;
    }

    /**
     * 檢查條件并返回檢查結(jié)果
     * @return
     */
    public boolean getCheckResult(){

        if(this.body == null||this.conditionList==null){
            throw new NullPointerException("檢查內(nèi)容和條件不能為空");
        }

        return check(this.body,this.conditionList);
    }

    @Override
    public boolean check(@NonNull Body body, @NonNull List<Condition> conditions) {

        for (Condition c : conditions) {
            if (!c.match(body)) {
                c.showTips(body);
                return false;
            }
        }
        return true;
    }


    public static Machine getCheckMachine(){
        return new Machine();
    }

    public static class Machine{

        private List<ContentChecker> checkerList;

        private Machine() {
            checkerList = new ArrayList<>();
        }

        public Machine putChecker(ContentChecker checker){
            checkerList.add(checker);
            return this;
        }

        /**
         * 檢查所有內(nèi)容
         * @return 結(jié)果
         */
        public boolean checkAll(){

            for(ContentChecker c:checkerList){
                if(!c.getCheckResult()){
                    return false;
                }
            }
            return true;
        }
    }

}

那么現(xiàn)在我檢查手機(jī)號(hào)和密碼就是這樣寫的了塌计。


            String phoneNum = mDataBing.edtPhone.getText().toString().trim();
            String password = mDataBing.edtPassword.getText().toString().trim();
            ContentBody phoneNumBody = new ContentBody("手機(jī)號(hào)", phoneNum);

            ContentBody passwordBody = new ContentBody("密碼", password);
            boolean result = ContentChecker.getCheckMachine()
                    .putChecker(ContentChecker.getChecker(phoneNumBody)
                            .addCondition(new NonNullCondition())
                            .addCondition(new PhoneNumCondition()))
                    .putChecker(ContentChecker.getChecker(passwordBody)
                            .addCondition(new NonNullCondition())
                            .addCondition(new BaseCondition() {
                                @Override
                                public boolean match(IContentChecker.Body body) {
                                    return body.getContent().length() >= 6;
                                }
                                @Override
                                public void showTips(IContentChecker.Body body) {
                                    ToastUtils.showShort("密碼不能少于6位");
                                }
                            }))
                    .checkAll();

result就是檢查手機(jī)號(hào)和密碼最后的結(jié)果。

以下是幾個(gè)常見的檢查條件

/**
 * 非空條件
 * @author XuNeverMore
 * @QQ 1045530120
 * @create on 2018/2/2 0002
 * @github https://github.com/XuNeverMore
 */

public class NonNullCondition extends BaseCondition{
    
    @Override
    public boolean match(IContentChecker.Body body) {
        return !TextUtils.isEmpty(body.getContent());
    }

    @Override
    public void showTips(IContentChecker.Body body) {
        //因?yàn)檫@里取得是body.getName()所以手機(jī)號(hào)或密碼為空的提示侯谁,該類都適用
        ToastUtils.showShort(body.getName()+"不能為空锌仅!");
    }
}


/**
 * 內(nèi)容長(zhǎng)度檢查條件
 * @author XuNeverMore
 * @QQ 1045530120
 * @create on 2018/2/2 0002
 * @github https://github.com/XuNeverMore
 */

public class LengthCondition implements IContentChecker.Condition{


    private int length;//最小長(zhǎng)度

    public LengthCondition(int length) {
        this.length = length;
    }

    @Override
    public boolean match(IContentChecker.Body body) {
        return !TextUtils.isEmpty(body.getContent())&&body.getContent().length()>=length;
    }

    @Override
    public void showTips(IContentChecker.Body body) {

        ToastUtils.showShort(body.getName()+"長(zhǎng)度不能少于"+length+"位");
    }
}

github源碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市墙贱,隨后出現(xiàn)的幾起案子热芹,更是在濱河造成了極大的恐慌,老刑警劉巖惨撇,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伊脓,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡魁衙,警方通過查閱死者的電腦和手機(jī)报腔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剖淀,“玉大人纯蛾,你說我怎么就攤上這事∽莞簦” “怎么了翻诉?”我有些...
    開封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)捌刮。 經(jīng)常有香客問我碰煌,道長(zhǎng),這世上最難降的妖魔是什么绅作? 我笑而不...
    開封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任芦圾,我火速辦了婚禮,結(jié)果婚禮上俄认,老公的妹妹穿的比我還像新娘个少。我一直安慰自己碍脏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開白布稍算。 她就那樣靜靜地躺著,像睡著了一般役拴。 火紅的嫁衣襯著肌膚如雪糊探。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天河闰,我揣著相機(jī)與錄音科平,去河邊找鬼。 笑死姜性,一個(gè)胖子當(dāng)著我的面吹牛瞪慧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播部念,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼弃酌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了儡炼?” 一聲冷哼從身側(cè)響起妓湘,我...
    開封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乌询,沒想到半個(gè)月后榜贴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妹田,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年唬党,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鬼佣。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驶拱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沮趣,到底是詐尸還是另有隱情屯烦,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布房铭,位于F島的核電站驻龟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缸匪。R本人自食惡果不足惜翁狐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凌蔬。 院中可真熱鬧露懒,春花似錦闯冷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至坎弯,卻和暖如春纺涤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抠忘。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工撩炊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人崎脉。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓拧咳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親囚灼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子骆膝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,855評(píng)論 25 707
  • 夜是夢(mèng)華麗的裙子 一個(gè)個(gè)被風(fēng)吹動(dòng)的故事 那些陌生的偶遇 在街角纏綿后分別 貓路過時(shí)踮起腳回眸 碧綠的眼睛打量著我 ...
    夢(mèng)里月光靜悄悄閱讀 285評(píng)論 0 0
  • 今天去看了奇跡男孩的這篇影片谭网,剛考完的時(shí)候我媽都哭了,但是我呢赃春,我是覺得這個(gè)片很好看愉择,當(dāng)然我覺得也很感動(dòng),首先有小...
    又呆又萌的萌閱讀 137評(píng)論 0 0
  • 如果你覺得有東西是錢買不到的织中,那說明你還是太窮锥涕。 如果這句話是真的。 我一定要努力賺好多好多好多錢狭吼, 然后買到一份...
    李欣悅1996L閱讀 130評(píng)論 0 0