react native 可以说是目前移动端最火的跨平台开发框架。给我感觉是开发一些简单界面没有问题,交互复杂的功能坑还是比较多。虽然坑很多,但是依然很火,我想主要有两点比较吸引人:
1. js开发界面,可以各个平台运行。
2. 热更新,大有取代apk插件化开发的趋势。当然apk实现插件化坑也很多,目前没有一个完善的解决方案,貌似也是在国内用得比较多,插件化在google基本都搜不到国外的什么文章的。
现在来说说使用RN开发遇到的第一个大坑,listview,对就是它,一个经常使用的组件,被称为核心组件之一的listview。出现的问题是这样的,我们的列表需要显示上千条数据,还需要列表能跳转到指定行。这两个需求在原生平台是很简单的事,so easy。但是RN的listview偏偏出问题了。
1. 列表还没滑到底部,android系统直接oom,内存溢出, 崩溃了。
2. 当需要跳转到某一行,如果这一行没有被绘制过,就跳转不过去。
这里不具体分析出现这两个问题的原因,大致是RN的listview使用的是系统的scrollview实现,使得listview没有办法进行ui复用,如果要显示的行过多,导致滑动越来越慢最后内存爆炸。由于是scrollview实现,没有添加到scrollview里面的行是不能跳转过去的。虽然listview可以指定使用RecyclerView作为底层实现,但是从源码看,并没有实现ui复用,结果同样内存溢出。
鉴于如上问题,不得不自定义RN的listview,达到UI复用,与原生系统性能一样的listview.
需要解决的问题:
1. 原生层做到UI复用。
2. js层做到UI和数据分离。我们知道目前RN UI和数据是没有分离的,listview每显示一行就要创建一行的view。1000行就要创建1000行view,内存肯定爆。
设计思路:
1. 原生层面使用RecyclerView,不使用listview,是为了方便以后功能扩展,复杂效果实现。
2. 在js层建立UI与数据的映射关系,UI与数据分离。
3.实现ui复用。
各个击破:
1. 原生层使用RecyclerView,做原生开发的都知道怎么使用,这里不赘述。
2. js层建立UI与数据映射关系。
建立映射的方式是,给要显示数据的view设置一个唯一标志,这个标志要求能在原生层取到,填充给这个view的数据使用同样的标志,这样就把数据和view对应上了,
在原生层根据这个对应关系吧数据填充到对应的view。例如:
js在render函数创建view:
<Text testID='test' style={
{marginLeft:3, fontSize: 16, color:'#555555', marginLeft:20}}>
aaaaaaaaaaaaa
</Text>
数据:[{'test':'real data','viewType':0}] //viewType是特殊字段,表示该数据对应的view类型
json数据的key与view的testID一样都是test,在原生层,根据数据的key test找到testID为test的view,然后用real data填充这个view。所以真正显示的数据是real data而不是aaaaaaaaaa。
如果有多种类型的view怎么办,还需要建立view类型的映射关系。我们先将render函数定义为 renderRow(index), index表现现在创建第几行view,比如:
var rowMap={"0":[3],"1":[0],"2":[1],"3":[2]};
rowMap的key:0, 1, 2, 3 表示一共有4种类型的view需要被显示, "0":[3]的意思是renderRow的index为3, 将要创建第4行view,这行view对应的类型是0。注意view类型必须是从0开始的整数。如