设计手机组件总结(精选5篇)

山崖发表网工作总结2024-03-18 09:53:3913

设计手机组件总结 第1篇

与 React/Vue 或者 iOS 相比,Android 的生命周期都比较复杂,如果要监听生命周期,一般情况下只能覆写 Activity / Fragment 的回调方法(onCreate、onResume、onPause、onDestroy 等),样板代码少不了,可维护性也变差。

如果要对生命周期进行简化,可以抽象成一个图,表示状态,线表示事件:

Lifecycle 负责处理这些点(states)和线(events),Activity / Fragment 是 LifecycleOwner,监听者则是 LifecycleObserver,一个非常清晰的观察者模式。

如果我们的组件需要强绑定声明周期,那么只需要借助 Lifecycle 去监听生命周期的状态和事件即可,再也不用覆写各种回调方法了。下面将要讲到的 LiveData 和 ViewModel 都是 Lifecycle-Aware Components,它们都用到了 Lifecycle。

Android 生命周期管理不当带来的最大问题就是内存泄露,举一个我们经常遇到的场景:一个异步任务(比如网络请求)持有了 UI 元素的引用,只要任务没有执行完,所有与这个 UI 元素有强引用关系的元素都没法被 GC,如果这样的场景多发生几次,很可能会引起 OOM。

为了异步对象引用的问题,最早我们使用 AsyncTask,任务执行在 worker thread,执行结果在主线程上发起回调。AsyncTask 的致命缺点是不支持流式数据(stream),而且回调嵌套太深(callback hell),与软件质量衡量指标之一的 maintainable 背道而驰,不好用自然就会慢慢被淘汰。

后来我们开始使用 RxJava,响应式编程,声明式写法,再借助 retrolambda 这种 backport,即使当年 Android 只支持到 JDK7,我们依然可以利用各种 operator 写出非常简洁的代码,“filter map 我闭~着眼”。RxJava 不但完美解决了线程调度的问题,还为我们提供了 OO 之外的抽象——作用在流上的 lambda,基于函数的抽象。但是,即便完美如斯,生命周期的问题依然无法回避,因为 Java 天生的局限性,一个 lambda 无论伪造地再像高阶函数,它本质上还是一个匿名内部类,这个匿名内部类依然持有对 outer class 实例的引用。于是我们必须通过 CompositeDisposable 来管理订阅关系,发起异步操作时记录订阅,离开页面时取消订阅,仍然需要覆写 onDestory 或者 onPause 。

如果我们以 Repository 层为界把架构蓝图分为上下两部分的话,上面的部分是数据展示,下面的部分是数据获取,数据获取部分因为要请求 Remote 数据,必然会依赖到线程调度,而数据展示必然运行在 UI 线程,与生命周期强相关,这个时候就需要 LiveData 登场了。

设计手机组件总结 第2篇

数据库作为数据持久层,其重要性不言而喻,当设备处于离线状态时,数据库可用于缓存数据;当多个 App 需要共享数据时,数据库可以作为数据源,但是基于原生 API 徒手写 CRUD 实在是痛苦,虽然 Github 上出现了不少 ORM 框架,但是它们的易用性也不敢让人恭维,直到 Room 出来之后,Android 程序员终于可以像 mybatis 那样轻松地操纵数据库了。

Room 是 SQLite 之上的应用抽象层,而 SQLite 是一个位于 Android Framework 层的内存型数据库。虽然 Realm 也是一个优秀的数据库,但是它并没有内置于 Android 系统,所会增大 apk 的体积,使用 Room 则没有这方面烦恼。

Room 的结构抽象得非常简单,数据对象(表名 + 字段)用 @Entity 注解来定义,数据访问用 @Dao 来注解,db 本身则用 @Database 来定义,如果要支持复杂类型,可以定义 @TypeConverters,然后在编译阶段,apt 会根据这些注解生成代码。Room 与 App 其他部分的交互如下图所示:

Entity 是一个数据实体,表示一条记录,它的用法如下:

Actor 是一个用 @Entity 注解的 data class,它会生成一个名字是 actors 的表,注意到有一个字段是 @Date? ,但是 SQLite 本身不支持这种复杂类型(complex type),所以我们还需要写一个可以转换成基础类型的转换器:

转换器通过 @TypeConverters 可作用于 class、field、method、parameter,分别代表不同的作用域。比如作用在 @Database 类的上,那么它的作用域就是 db 中出现的所有 @Dao@Entity

代码出现的 ActorDao 定义了 CRUD 操作。用 @Dao 来注解,它既可以是一个接口,也可以是抽象类,用法如下:

@Query 中的 SQL 语句可以直接引用方法参数,而且它的返回值可以是 LiveData 类型,也支持 Flowable 类型,也就是说,Room 原生支持响应式,这是对数据驱动最有利的支持,也是 Room 区别于其他 ORM 框架的显著特征。

至此,我们可以确定,无论数据来自 Remote 还是来自本地 DB,架构蓝图中的 Repository 对 ViewModel 提供的数据可以永远是 LiveData 类型,接下来我们看一下 ViewModel 的妙用。

设计手机组件总结 第3篇

这是最常用的一种导航形式。底部导航栏位于页面底部,操作方便。但也是因为位于底部,所以导航栏里各个tab的内容不是很突出。

如果你更想让用户时时注意到应用的每个tab的标题,那么顶部tab导航更合适。

另外,底部导航栏有两种用法:

如果用户要去往另一个tab页面,用户必须一步步返回或者从头开始重新选择。

层级导航示意

另一种是扁平导航,扁平导航允许用户在多个内容分类之间切换。网易云音乐和App Store使用了这种导航形式。

扁平导航示意

关于两者在用法上的详细区别,请参考之前写过的这篇文章:掌握了这个导航控件,你可以设计80%的应用导航

设计手机组件总结 第4篇

这种导航,用在某个页面里比较多见(比如新闻列表页),但使用列表来对整个应用进行导航,即应用的最顶层选项以列表形式呈现,还是相对少见的。

虽然少见,沐风还是找到了一些典型的例子:QQ邮箱的导航是以列表的形式组织起来的。

iOS自带的备忘应用,也是使用的列表导航形式。

另外,iOS系统的设置,以及Siri的启示页面,都使用了列表导航:

观察一下上面这些页面,它们有两个特点:

那么,具体应该选用哪种?答案是:按照用户是“有明确目标”还是”无目的浏览”决定。

如果用户有明确目标,那么列表导航能在一页展示多条项目,方便用户高效查找;而如果用户没有明确的目标,只是随意的浏览,那么顶部tab要更友好,因为每个tab里的内容都直接展示出来,方便用户查看。

但是,顶部tab导航里的选项,越靠后,浏览量越小。如下图所示,由于选项9需要用户连续划动8次,所以能够看到该选项内容的用户已经很少了。

设计手机组件总结 第5篇

在许久以前,网易新闻客户端就采用的抽屉导航。后来版本升级,改为了底部导航栏形式。由于导航里的选项得到了更好的曝光(常驻在底部导航栏里),因此几个tab的访问数据都得到了明显的提升。

这种设计,无形中加强了用户进入个人页的操作便利性,符合QQ需要突出个人页的产品需要。

以上总结了8种导航结构:

沐风,微信公众号:沐风与体验设计。人人都是产品经理专栏作家,2017年度作家评选最佳人气奖。爱奇艺资深交互设计师。留德海龟,曾任职腾讯微生活、网易、宜人贷。6年交互设计经验,专注设计领域,欢迎关注。

题图来自Unsplash,基于CC0协议

显示全文

注:本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即后台留言通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意

点击下载文档

文档为doc格式

发表评论

评论列表(7人评论 , 39人围观)

点击下载
本文文档