一、简介
Texture(原名AsyncDisplayKit)是FaceBook开源的一款能够保持界面流畅的框架。建立在UIKit之上,可以保持最复杂的用户界面的流畅和响应。(smooth and responsive); 最初诞生于 Facebook 的 Paper 应用程序。它是为了解决 Paper 团队面临的核心问题之一:如何尽可能缓解主线程的压力?
Texture 是达摩克利斯之剑, 所以再选择这个框架的时候需要额外的斟酌. 先确认弊端,再决定是否项目中要不要去使用它吧
1、使用优缺点
- 需要自己造轮子
- 不支持大家常用的storyboard、xib、autoLayout,影响开发效率
- 代码没有UIKit使用熟练
- 网上资源少
- 但是可以和UIKit混合开发
2.优化原理
布局:
iOS自带的Autolayout在布局性能上存在瓶颈,并且只能在主线程进行计算。(参考Auto Layout Performance on iOS)因此ASDK弃用了Autolayout,自己参考自家的ComponentKit设计了一套布局方式。渲染
对于大量文本,图片等的渲染,UIKit组件只能在主线程并且可能会造成GPU绘制的资源紧张。ASDK使用了一些方法,比如图层的预混合等,并且异步的在后台绘制图层,不阻塞主线程的运行。系统对象创建与销毁
UIKit组件封装了CALayer图层的对象,在创建、调整、销毁的时候,都会在主线程消耗资源。ASDK自己设计了一套Node机制,也能够调用。实际上,从上面的一些解释也可以看出,ASDK最大的特点就是”异步”。
将消耗时间的渲染、图片解码、布局以及其它 UI 操作等等全部移出主线程,这样主线程就可以对用户的操作及时做出反应,来达到流畅运行的目的。
ASDK 认为,阻塞主线程的任务,主要分为上面这三大类。
为了尽量优化性能,ASDK 尝试对 UIKit 组件进行封装:
3.Nodes节点
如果你之前使用过views,那么你应该已经知道如何使用nodes,大部分的方法都有一个等效的node,大部分的UIView和CALayer的属性都有类似的可用的。任何情况都会有一点点命名差异(例如,clipsToBounds和masksToBounds),node基本上都是默认使用UIView的名字,唯一的例外是node使用position而不是center
当然,你也可以直接访问底层view和layer,使用node.view和node.layer
关系图
这是常见的 UIView 和 CALayer 的关系:View 持有 Layer 用于显示,View 响应触摸事件。
- Node控件
ASDK UIKit ASDisplayNode UIView ASCellNode UITableViewCell/UICollectionViewCell ASTextNode UILabel ASImageNode/ASNetworkImageNode UIImageView ASVideoNode AVPlayerLayer ASControlNode UIControl ASScrollNode UIScrollView ASEditableTextNode UITextView ASMultiplexImageNode(图片管理) UIImageView
静态库
AsyncDisplayKit可以当做静态库引入
- 拷贝整个工程到你的目录下,添加AsyncDisplayKit.xcodeproj到你的workspace
- 在build phases中,在Target Dependencies下添加AsyncDisplayKit Library
- 在build phases中,添加libAsyncDisplayKit.a, AssetsLibrary, Photos等框架到Link Binary With Libraries中
- 在build settings中,添加-lc++和-ObjC到 project linker flags
二、使用
主要介绍常用控件ASTableNode/ASCollectionNode的使用,代码放在GitHub上的ASDK_Demo。
1.ASImageNode
- 使用ASNetworkImageNode的URL设置网络图片。
- ASNetworkImageNode有图片下载的ASNetworkImageNodeDelegate
- ASImageNode使用ASDK的图片管理类PINCache,PINRemoteImage
- 如果不打算引入PINRemoteImage和PINCache,你会失去对jpeg的更好的支持,你需要自行引入你自己的cache系统,需要遵从ASImageCacheProtocol
2.ASTextNode
ASTextNode没有text属性,只能使用attributedText
1 | //居中 |
3.ASTableNode/ASCollectionNode
- ASTableNode/ASCollectionNode不支持复用机制,每次滚动都会重新创建cell。
- ASTableNode并不提供类似UITableview的-tableView:heightForRowAtIndexPath:方法,这是因为节点基于自己的约束来确定自己的高度,就是说你不再需要写代码来确定这个细节,一个node通过-layoutSpecThatFits:方法返回的布局规则确定了行高,所有的节点只要提供了约束大小,就有能力自己确定自己的尺寸
- 使用 Batch Fetching 进行无限滚动,即预加载功能
三、布局
ASDK 拥有自己的一套成熟布局方案,虽然学习成本略高,但至少比原生的 AutoLayout 写起来舒服,重点是性能比起 AutoLayout 好的不是一点点。(ASDK不支持autoLayout)
1 | //下面这个方法就是用来建立布局规则对象,产生 node 大小以及所有子 node 大小的地方,你创建的布局规则对象一直持续到这个方法返回的时间点,经过了这个时间点后,它就不可变了。尤其重要要记住的一点事,千万不要缓存布局规则对象,当你以后需要他的时候,请重新创建。 |
1. 布局类
- ASAbsoluteLayoutSpec(绝对布局约束)
- ASBackgroundLayoutSpec(背景布局规则)
- ASInsetLayoutSpec(边距布局规则)
- ASOverlayLayoutSpec(覆盖布局规则)
- ASRatioLayoutSpec(比例布局规则)
- ASRelativeLayoutSpec(相对布局规则)
- ASCenterLayoutSpec(中心布局规则)
- ASStackLayoutSpec(堆叠布局规则)
- ASWrapperLayoutSpec (填充布局规则)
2.示例
ASAbsoluteLayoutSpec
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
使用方法和原生的绝对布局类似
ASBackgroundLayoutSpec
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
把childNodeA 做为 childNodeB 的背景,也就是 childNodeB 在上层,要注意的是 ASBackgroundLayoutSpec 事实上根本不会改变视图的层级关系
ASInsetLayoutSpec
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
_childNode 相对于父视图边距都为 0,相当于填充整个父视图。
ASOverlayLayoutSpec
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
类似于ASBackgroundLayoutSpec,都是设置层级关系
###ASRatioLayoutSpec
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
比较常用的一个类,作用是设置自身的高宽比,例如设置正方形的视图
###ASRelativeLayoutSpec
1 | //把 childNodeA 显示在右上角。 |
它可以把视图布局在:左上、左下、右上、右下四个顶点以外,还可以设置成居中布局。
###ASCenterLayoutSpec
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
###ASWrapperLayoutSpec
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
填充整个视图
##ASStackLayoutSpec
可以说这是最常用的类,而且相对于其他类来说在功能上是最接近于 AutoLayout 的。
之所以称之为盒子布局是因为它和 CSS 中 Flexbox 很相似,不清楚 Flexbox 的可以看下这篇博客(HTML布局)。
示例
1 | - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{ |
简单的说明下各个参数的作用:
1.direction
:主轴的方向,有两个可选值:
- 纵向:
ASStackLayoutDirectionVertical
(默认)- 横向:
ASStackLayoutDirectionHorizontal
2.
spacing
: 主轴上视图排列的间距,比如有四个视图,那么它们之间的存在三个间距值都应该是spacing
3.justifyContent
: 主轴上的排列方式,有五个可选值:
ASStackLayoutJustifyContentStart
从前往后排列ASStackLayoutJustifyContentCenter
居中排列ASStackLayoutJustifyContentEnd
从后往前排列ASStackLayoutJustifyContentSpaceBetween
间隔排列,两端无间隔ASStackLayoutJustifyContentSpaceAround
间隔排列,两端有间隔4.
alignItems
: 交叉轴上的排列方式,有五个可选值:
ASStackLayoutAlignItemsStart
从前往后排列ASStackLayoutAlignItemsEnd
从后往前排列ASStackLayoutAlignItemsCenter
居中排列ASStackLayoutAlignItemsStretch
拉伸排列ASStackLayoutAlignItemsBaselineFirst
以第一个文字元素基线排列(主轴是横向才可用)ASStackLayoutAlignItemsBaselineLast
以最后一个文字元素基线排列(主轴是横向才可用)5.
children
: 包含的视图。数组内元素顺序同样代表着布局时排列的顺序
- 本文作者: 醉疏狂
- 本文链接: https://hubin97.github.io/2018/05/11/Texture/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!