关于一般界面程序的一些想法

智数银月引
• 阅读 2072

很多时候,我们去写东西的时候,都是闷头写,写到哪算哪,知道一些重构技巧的同学可能会在边写的时候遇到重复就提取出来成方法这样,但这样一开始是蛮好的,因为你自己写的东西,你都知道,但是写久了,你回头一看,卧槽,怎么这么多小方法?!时间久了,你再回来定位问题的时候,你就会发现方法太多,导致了一个很重要的问题就是,调用层次很混乱,你很难找到你想要的那个方法,总之就这个意思,有遇到这个问题的,自然心里有所体会。

我举个例子,比如说,产品需求让我们点下一个按钮,就发个网络请求,然后让UI显示“请求中”,数据回来的时候,再显示正确的UI。好,那么应该是这样的:

void onClick(View v) {
    switch (v.getId()) {
        case myButtonId:
            requestData();
            mButton.setText("请求中");
            break;
    }
}

void requestData() {
    // ...
}

void onRequestCallback(Data data) {
    // 回调来了,更新UI
    mButton.setText(data.toString());
}

首先,这样写是有问题的,我上一篇文章已经说过这样的问题了。问题在于就地去更新UI了。我们要用一个统一的地方来更新UI,于是这个要改写成:

Data mData = null;
boolean mIsRequesting = false;

void onClick(View v) {
    switch (v.getId()) {
        case myButtonId:
            requestData();
            break;
    }
}

void requestData() {
    mIsRequesting = true;
    // 发起请求
    updateView()    
}

void onRequestCallback(Data data) {
    // 回调来了,更新UI
    mIsRequesting = false;
    mData = data;
    updateView();
}

// 用统一的方法更新UI,并且按照View分类
void updateView() {
    if (mIsRequesting) {
        mButton.setText("请求中");
    } else {
        if (mData != null) {
            mButton.setText(data.toString());
        }
    }
}

用统一的方法去更新UI,这个说法是很通俗的,我想谁都可以听明白吧,其实这个事情,是可以更加抽象的,也就是说,它可以是一种抽象,适应别的情况,最近我刚好又做了一些重构的工作,已经成功领悟到这个抽象,那就是:一个方法只去做一件事情,更准确的说,只做一类事情,或者说,一类事情只丢到一个方法里去做。不知道这样说,大家听明白没有。

说一个Android里面的范本吧。想想onMeasure,onLayout,onDraw方法,单看onDraw方法,就是我上次说到的用统一的方法去更新UI,你三个方法一起看,你就明白了,一个方法只做一类事情,一类事情只丢到一个方法里去做

onLayout里面需要的数据,都在onMeasure里去做好了,存到成员变量上,onLayout直接用,onDraw需要的东西,前两个步骤都做好了,onDraw直接用成员变量上的东西。换句话说,UI只关心它要展示的数据源,而不关心数据源的改变

UI上的代码,至始至终都是直接拿着数据源来搞,而逻辑,改变数据源后,不要就地去更新UI,而应该调用更新UI的方法,这样,维护数据,展示数据,两个部分就得到了分离,维护性就是这样来的。

那么,我们写一个界面程序,每次都闷头写吗?有没有什么套路呢?我就在想,是不是有一种共性,有一种通用的做法,一种高屋建瓴的理解,可以在一开始就让代码漂亮呢。经过我仔细思考和总结后,有了如下的体会。大概是这样:

其实界面程序主要分为两个部分:处理数据处理UI

处理数据其实是很宽泛的,包括处理内存的数据,处理本地的数据,处理网络的数据。你存成员变量,一个列表排序,其实都是处理内存中的数据,下载文件,存配置到文件,其实就是处理本地的数据,发送网络请求,处理回包,其实就是处理网络的数据,处理回包其实是从网络到内存。

处理UI其实就是更新UI,或者动画什么的,动画什么的其实没关系,随便搞吧,没啥。更新UI其实是时刻关注着内存中的数据,内存中的数据就决定UI要展示成什么样。

接下来再思考一下,方法的层次/分类。这个就是说,方法应该分成哪些类别,哪些方法是有相同的特点。其实可以分为三类:

  • 时机/用户操作

  • 逻辑/处理数据

  • 更新UI

时机/用户操作,是整个界面程序的驱动力,整个界面能运作起来,完全是靠这些方法。比如

onCreate
onStart
onClick
onDestory
onCallback // 网络数据回调
onTimer    // timer,定时器

这一类方法,是第一层,最先被调用的方法。这些方法被调用后,里面就是我们的逻辑部分,或者数据部分,比如用户输入了什么要存起来啊,点了个按钮发起网络请求啊。这一层方法,我们可以自己命名,自己建,随便自己搞。比如:

requestData
handleData
doXXXXXX

最后一类,就是更新UI的方法,按我现在的理解,只需要一个就行了。

updateView

因此第一层方法,可以调用第二层方法,和第三层方法。第二层方法,可以调用第三层方法。按照这样的逻辑进行组织,逻辑就会清晰的多。

总结:

  • 一类工作放到一个方法中处理,一个方法只处理一类工作

  • 要注意整个界面中所有方法的层次,要有整体的把握,不要无谓的为了抽象,重用增加方法,应当减少方法,让整体逻辑和调用顺序清晰起来

  • 在实际操作之前,先整理下,有哪些网络请求,数据要如何处理,UI关心哪些数据,然后再着手去做

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
4年前
Java多线程带返回值的Callable接口
Java多线程带返回值的Callable接口在面试的时候,有时候是不是会遇到面试会问你,Java中实现多线程的方式有几种?你知道吗?你知道Java中有可以返回值的线程吗?在具体的用法你知道吗?如果两个线程同时来调用同一个计算对象,计算对象的call方法会被调用几次你知道吗?如果这些你知道,那么凯哥(凯哥Java:kaigejava)恭喜你,本文你可以不用
Stella981 Stella981
4年前
Oh! Binlog还能这样用之Canal
背景不知道是否你还在为下面的问题而困扰:当你使用了redis或者其他中间件做缓存的时候,经常发现缓存和数据库的数据不一致,只能通过定时任务或者缓存过期的方式去做一些限制。当你使用了ES做搜索工具,使用双写的那一套方法,还在为ES和数据库不是一个事务而担忧。当你需要迁移数据的时候,也还在使用双写的方法,如果是同一个数据
Wesley13 Wesley13
4年前
JDK核心JAVA源码解析(1)
想写这个系列很久了,对自己也是个总结与提高。原来在学JAVA时,那些JAVA入门书籍会告诉你一些规律还有法则,但是用的时候我们一般很难想起来,因为我们用的少并且不知道为什么。知其所以然方能印象深刻并学以致用。首先我们从所有类的父类Object开始:1\.Object类(1)hashCode方法和equals方法
Stella981 Stella981
4年前
Intellij IDEA神器居然还有这些小技巧
概述IntellijIDEA真是越用越觉得它强大,它总是在我们写代码的时候,不时给我们来个小惊喜。出于对IntellijIDEA的喜爱,我决定写一个与其相关的专栏或者系列,把一些好用的IntellijIDEA技巧分享给大家。本文是这个系列的第一篇,主要介绍一些你可能不知道的但是又实用的小技巧。我最爱
Wesley13 Wesley13
4年前
JDK核心JAVA源码解析(4)
想写这个系列很久了,对自己也是个总结与提高。原来在学JAVA时,那些JAVA入门书籍会告诉你一些规律还有法则,但是用的时候我们一般很难想起来,因为我们用的少并且不知道为什么。知其所以然方能印象深刻并学以致用。本篇文章针对堆外内存与DirectBuffer进行深入分析,了解Java对于堆外内存处理的机制,为下一篇文件IO做好准备Java堆栈内存与堆外内
Stella981 Stella981
4年前
Oh!Binlog还能这样用之Canal
背景不知道是否你还在为下面的问题而困扰:当你使用了redis或者其他中间件做缓存的时候,经常发现缓存和数据库的数据不一致,只能通过定时任务或者缓存过期的方式去做一些限制。当你使用了ES做搜索工具,使用双写的那一套方法,还在为ES和数据库不是一个事务而担忧。当你需要迁移数据的时候,也还在使用双写的方法,如果是同一个数据
Wesley13 Wesley13
4年前
Java后端学习路线
自学/学习路线这样的一期我想写很久了,因为一直想写的全一点硬核一点所以拖到了现在,我相信这一期对不管是还在学校还是已经工作的同学都有所帮助,不管是前端还是后端我都墙裂建议大家看完,因为这样会让你对你所工作的互联网领域相关技术栈有个初步的了解。你们也知道敖丙我是个创作鬼才,常规的切入点也不是我的风格,我毕业后主要接触的都是电商领域,所以这一期我把目前所了解
Wesley13 Wesley13
4年前
JDK核心JAVA源码解析(7)
想写这个系列很久了,对自己也是个总结与提高。原来在学JAVA时,那些JAVA入门书籍会告诉你一些规律还有法则,但是用的时候我们一般很难想起来,因为我们用的少并且不知道为什么。知其所以然方能印象深刻并学以致用。本篇文章针对JAVA中集合类LinkedList进行分析,通过代码解释Java中的Failfast设计思想,以及LinkedList底层实现和与A
Wesley13 Wesley13
4年前
JDK核心JAVA源码解析(8)
想写这个系列很久了,对自己也是个总结与提高。原来在学JAVA时,那些JAVA入门书籍会告诉你一些规律还有法则,但是用的时候我们一般很难想起来,因为我们用的少并且不知道为什么。知其所以然方能印象深刻并学以致用。本文基于Java14在JDK1.5引入自动装箱/拆箱,让开发更高效。自动装箱时编译器调用valueOf()将原始类型值转换成对象,同
掌握了这几个 Linux 命令可以让你工作效率提升三倍
很多程序员熟悉了在Windows环境下开发,而我们服务器一般都是Linux系统。当有一天你需要在Linux服务器上做一些配置或者故障排除的时候,你会很困惑,不知道如何下手。原因是对Linux常用的命令还不熟悉,今天我就给大家介绍几个Linux常用命令。掌握它们的用法后,我们在使用CRMEB打通版系统的时候就能如鱼得水,可以大大提高工作
linbojue linbojue
2星期前
Kafka高性能揭秘:零拷贝、顺序写与页缓存,千万级吞吐量的底层原理深度剖析
很多同学在面试时都能背出那几句八股文:“零拷贝、顺序写、页缓存”。但如果面试官追问一句:“你能在Java里写出零拷贝的代码吗?你知道页缓存什么时候会失效吗?Kafka的索引文件为什么要用mmap而不是sendfile?”这时候,很多人就开始支支吾吾了。😅
智数银月引
智数银月引
Lv1
时间会融化掉所有的尖锐。
文章
3
粉丝
0
获赞
0