热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android—facebook/litho框架超实用的入门干货

Android---facebooklitho框架超实用的入门干货可能很多人不知道litho是什么,我这里简单说一下litho就是用代码写布局。嗯,就是那么简单。或许你会问为什么用

可能很多人不知道litho是什么,我这里简单说一下litho就是用代码写布局。嗯,就是那么简单。或许你会问为什么用代码来写呢 我
xml用的挺好也方便,至于这些问题 我都不会回答(坏笑) 说了是干货所以肯定以代码为主 所以这些介绍我能省就省了。其实网上有很多大神从框架层面介绍了litho的好处和作用,可以解答这些问题。读完之后就知道litho的好处啦。但可惜的是介绍litho用法的文章却是少之又少(可能是因为litho算是比较新颖的框架  而大神忙着研究框架和源码吧)

既然是入门 本章涉及的内容就不会太深 主要就是实现一个简单的listView和item的点击事件而已。可能有些人会觉得这太简单了,我下个demo一看不就懂了吗。我可以告诉你,你看了demo可能也不知道怎么实现(知道了的求放过,只能说明你很厉害)原因有两点:
1.因为litho有点像编写AIDL时Android自动会生成一个Binder 类,如果你不知道这点 那么也就无法继续下去了。
2.又类似于Dagger  代码老是变红 让你觉得你的代码是错的(这个就很烦)
好废话不多说 下面就开始吧(其实已经说了好多废话)

litho的官方gitbub   
https://github.com/facebook/litho
除了demo里面还有官方的文档的url哦(其实我做的工作就是将文档中的一部分整理出来告诉你罢了)

想使用facebook的litho第一步很简单自然是导包啦

// Litho
implementation 'com.facebook.litho:litho-core:0.21.0'
implementation 'com.facebook.litho:litho-widget:0.21.0'
compileOnly 'com.facebook.litho:litho-annotations:0.21.0'
annotationProcessor 'com.facebook.litho:litho-processor:0.21.0'
// SoLoader
implementation 'com.facebook.soloader:soloader:0.5.1'
// For integration with Fresco
implementation 'com.facebook.litho:litho-fresco:0.21.0'
// For testing
testImplementation 'com.facebook.litho:litho-testing:0.21.0'
//下面是可选的库
// Sections
implementation 'com.facebook.litho:litho-sections-core:0.21.0'
implementation 'com.facebook.litho:litho-sections-widget:0.21.0'
compileOnly 'com.facebook.litho:litho-sections-annotations:0.21.0'
annotationProcessor 'com.facebook.litho:litho-sections-processor:0.21.0'

Jetbrains全家桶1年46,售后保障稳定

 我们在写列表效果的时候也会用到所以也先导入啦!!!  第一步完成
这里需要注意的是我的support都是27.1.1 因为写26时 会有错误的提示 那还是按照他的提示改成新的吧
implementation ‘com.android.support:appcompat-v7:27.1.1’
implementation ‘com.android.support:recyclerview-v7:27.1.1’

第二步 初始化litho
写一个SampleApplication继承Application并在onCreate()当中初始化SoLoader.init(this, false);
当然SampleApplication的名字你可以自己取啦

public class SampleApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
System.out.println("App oncreate");
SoLoader.init(this, false);
}
}

需要注意的是一定要在xml中将你定义的Application引入哦!!当然这些都很简单 小心点就是了
第二步也完成啦

第三步 开始实现一个简单页面

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ComponentContext cOntext= new ComponentContext(this);
final Component compOnent= Text.create(context)
.text("Hello World")
.textSizeDip(50)
.build();
setContentView(LithoView.create(context, component));
}

这样一个简单的Hello World就出来啦   
从这里可以看出我们要初始化一个控件并没有依赖xml,而是通过代码”new”出来的。

那么有一个item总不会只有一个TextView 可能有2个TextView或者ImageView等等 这样的话我们就需要定义一个类去慢慢的编写出想要的item布局了。
首先我们定义一个类 叫ListItemSpec  这个名字很重要我等下会说 先附上ListItemSpec的代码

@LayoutSpec
public class ListItemSpec {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c) {
return Column.create(c)
.paddingDip(ALL, 16)
.backgroundColor(Color.WHITE)
.child(
Text.create(c)
.text("Hello world")
.textSizeSp(40))
.child(
Text.create(c)
.text("Litho tutorial")
.textSizeSp(20))
.build();
}
}

类似效果

Android ---facebook/litho框架 超实用的入门干货

代码很简单 就这么多 那么我们解释一下其中可能看不懂或者一些注意的东西
其中Column.create(c)可以理解为 自定义一个View 类似上面的Text.create(context) 就是一个TextView 只不过TextView的定义
Litho已经帮我们实现了名字叫Text 那么我们定义的这个View就是2个TextView组成的 没有名字自然是用Column来实现,如果你想要ImageView和TestView结合 自然类似如此的写法来组成(ImageView是Image.create)。.paddingDip、.backgroundColor这些自然是边距和背景色。
其实看到这里有小伙伴们有疑惑 如果我想要更复杂的item怎么办呢。 那现阶段可能干货确实比较少,而我也并不可能列出所有api一一解释,所以有需求的小伙伴们可以进入官网来查看,好在他们的api名字和xml中相差无几,其实试试也就知道了。
那么简单的自定义控件就完成啦 其中代码中的注解@LayoutSpec 和 @OnCreateLayout很重要 别写漏了
现在我们将MianActivity中的HelloWord替换成我们自定义的控件吧

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ComponentContext cOntext= new ComponentContext(this);
final Component compOnent= Text.create(context)
.text("Hello World")
.textSizeDip(50)
.build();
final Component component1 = ListItem.create(context)
.color(Color.WHITE)
// .title("Hello, world!")
// .subtitle("Litho tutorial")
.build();
setContentView(LithoView.create(context, component1));//将其替换成component1
}

写到这里相信可能已经有小伙伴出现各种问题了。有人会问 你定义了一个ListItemSpec类却没用 这里用了一个ListItem.create还报红了你是不是不小心写错啦。这里我说明一下,这里我并没有写错 你也没有看错了 就是ListItem.create(context)。那么这个
ListItem哪里来的呢。其实这里就是我上面说像AIDL自动生成的类啦 你写了ListItemSpec里面加了一些注解那么litho就会自动帮你生成ListItem类(暂时可以这么理解 具体框架的实现机制这里就不做说明了),当然这并不是说所有的类都可以这样生成的,有2点需要注意的事情:
1.类名后面必须要以Spec结尾 不然会报错哦
2.注解不要忘记啦
那还有些小伙伴说 我这个类都没有错啊 也是这样写了 可是为什么ListItem.create(context)没法import呢 需要import那个包呢。其
实这里的ListItem是不需要import可能代码会报红 但是运行一下就好了(在吐槽下 这个好烦)所以在敲下面的.color(Color.WHITE)的方法时都是要像txt文本一样敲代码了 提示都没(这个好烦)。 然后就你运行成功之后发现ListItem就不报红了吧。

其实理解了上面这个”自动生成的规则后 再看demo就会明白了 该去找什么类 为什么 demo中的ListItem死活找不到”
这样的item就结束了吗 是不是还缺少了什么重要的东西。 没错 就是数据啦 上面的ListItemSpec类中text和textSizeSp都是写死的
那么如何传递数据呢 其实也很简单 还要借助注解的力量
在ListItemSpec类的onCreateLayout参数中加入@Prop String title

@LayoutSpec
public class ListItemSpec {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c,
@Prop String title,) {
return Column.create(c)
.paddingDip(ALL, 16)
.backgroundColor(Color.WHITE)
.child(
Text.create(c)
.text(title)//这样title就不是死数据了 其他的也类似这种写法
.textSizeSp(40))
.child(
Text.create(c)
.text(title)
.textSizeSp(20))
.build();
}
}
//这是mainActivity的 别和上面看成一个类哦
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ComponentContext cOntext= new ComponentContext(this);
final Component compOnent= Text.create(context)
.text("Hello World")
.textSizeDip(50)
.build();
final Component component1 = ListItem.create(context)
.color(Color.WHITE)
.title("Hello, world!") //这里的title会传入定义的@Prop String title当中 注解和名字都不能错哦
// .subtitle("Litho tutorial")
.build();
setContentView(LithoView.create(context, component1));//将其替换成component1
}

那么数据也可以正常的传入了 最后的就是点击事件了,既然是item的点击事件 那就先吧布局变成list的吧

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ComponentContext cOntext= new ComponentContext(this);
final Component compOnent= Text.create(context)
.text("Hello World")
.textSizeDip(50)
.build();
final Component component1 = ListItem.create(context)
.color(Color.WHITE)
.title("Hello, world!") //这里的title会传入定义的@Prop String title当中 注解和名字都不能错哦
// .subtitle("Litho tutorial")
.build();
final Component component2 =
RecyclerCollectionComponent.create(context)
.disablePTR(true)
.section(ListSection.create(new SectionContext(context)).build())
.build();
setContentView(LithoView.create(context, component2));//将其替换成component2
}

我没有将原来的Component删除掉是因为让你们做个对比而已。 列表形式litho其实也已经帮我我们写好了使用
RecyclerCollectionComponent就可以了(这就是可选库里的东东哦),其中disablePTR(true)的意思就是静止刷新(PTR就是
PullToreFresh的缩写啦)
可以看到我这里使用了ListSection.create那么按照之前的逻辑肯定会有ListSectionSpc的类啦 代码都是由前面讲解的基础类所组成
就不在一一重复 需要注意的也已经用注释写上啦 直接上代码

@GroupSectionSpec
public class ListSectionSpec {
@OnCreateChildren
static Children onCreateChildren(final SectionContext c) {
Children.Builder builder = Children.create();
ListItem child = ListItem.create(c)
.color(Color.WHITE)
.title("Hello, world!")
.subtitle("Litho tutorial")
.build();
// for (int i = 0; i <32; i++) {
// builder.child(
// SingleComponentSection.create(c)
// .key(String.valueOf(i))
// //如果ListItemSpec定义了title color等属性 而这里不设置 直接将ListItem.create(c).build()
// //传入将会报空指针 而且错误难以排查
// .component(child));
// }
//和上面的效果一样
DataDiffSection.Builder child1 = DataDiffSection.create(c)
.data(generateData(32))
.renderEventHandler(ListSection.onRender(c));
builder.child(child1);
return builder.build();
}
@OnEvent(RenderEvent.class)
static RenderInfo onRender(final SectionContext c, @FromEvent Integer model) {
return ComponentRenderInfo.create()
.component(
ListItem.create(c)
.color(model % 2 == 0 ? Color.WHITE : Color.LTGRAY)
.title(model + ". Hello, world!")
.subtitle("Litho tutorial")
.build())
.build();
}
private static List generateData(int count) {
final List data = new ArrayList<>(count);
for (int i = 0; i data.add(i);
}
return data;
}
}

实现的效果类似

Android ---facebook/litho框架 超实用的入门干货

至此列表页面也已经完成 最后来添加一下item的点击事件吧

@LayoutSpec
public class ListItemSpec {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c,
@Prop String title,) {
return Column.create(c)
.paddingDip(ALL, 16)
.backgroundColor(Color.WHITE)
.child(
Text.create(c)
.text(title)//这样title就不是死数据了 其他的也类似这种写法
.clickHandler(ListItem.onFaceClicked(c, title))) //添加点击事件 title是数据
.textSizeSp(40))
.child(
Text.create(c)
.text(title)
.textSizeSp(20))
.build();
}
//点击事件的回调
@OnEvent(ClickEvent.class)
static void onFaceClicked(
ComponentContext c,
@Param String face) { //@Param String face上面传递过来的数据 @Param注解很重要哦
Log.d("FacePileComponent", "Face clicked: " + face);
}
}

点击事件也添加完毕了
最后的最后就我个人意见来总结一下litho吧。
优点:
1.可定义性\可声明: 就是可以用api来定义你的ui,减少了xml的部分,而且布局和逻辑代码分别更为清晰了
2.异步布局:Litho可以在不阻塞UI线程的情况下提前测量和布局UI。
3.视图扁平化:Litho使用Yoga进行布局,并自动减少UI中包含的ViewGroup的数量。
4.细粒度回收:任何组件(如文本或图像)都可以在UI中的任何地方回收和重用。
缺点:
1.由于大部分利用了注解和自动生成的类,导致一旦代码出错就难以排查,因为不能马上定位到出错的地方,而需要你自己稍加分析
2.写代码是要编译一遍才会生成类 不然只能手打了
3.目前资源较少 遇到难题无法快速借鉴大神的解决方法或者思路

个人认为如果不是较为复杂的页面尤其是较为复杂的列表(item有gif动图或者短视频等等)暂时还不建议使用litho。毕竟
RecyclerView对于一般列表已经能够胜任。而且框架已经较为成熟。但是对于在性能方面有要求的app请务必使用litho,上面的优点中,尤其是第4点极大优化了列表的性能。


推荐阅读
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文介绍了一些Java开发项目管理工具及其配置教程,包括团队协同工具worktil,版本管理工具GitLab,自动化构建工具Jenkins,项目管理工具Maven和Maven私服Nexus,以及Mybatis的安装和代码自动生成工具。提供了相关链接供读者参考。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • Netty源代码分析服务器端启动ServerBootstrap初始化
    本文主要分析了Netty源代码中服务器端启动的过程,包括ServerBootstrap的初始化和相关参数的设置。通过分析NioEventLoopGroup、NioServerSocketChannel、ChannelOption.SO_BACKLOG等关键组件和选项的作用,深入理解Netty服务器端的启动过程。同时,还介绍了LoggingHandler的作用和使用方法,帮助读者更好地理解Netty源代码。 ... [详细]
  • 今日份分享:Flutter自定义之旋转木马
    今日份分享:Flutter自定义之旋转木马-先上图,带你回到童年时光:效果分析子布局按照圆形顺序放置且平分角度子布局旋转、支持手势滑动旋转、快速滑动抬手继续旋转、自动旋转支持X轴旋 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 【MicroServices】【Arduino】装修甲醛检测,ArduinoDart甲醛、PM2.5、温湿度、光照传感器等,数据记录于SD卡,Python数据显示,UI5前台,微服务后台……
    这篇文章介绍了一个基于Arduino的装修甲醛检测项目,使用了ArduinoDart甲醛、PM2.5、温湿度、光照传感器等硬件,并将数据记录于SD卡,使用Python进行数据显示,使用UI5进行前台设计,使用微服务进行后台开发。该项目还在不断更新中,有兴趣的可以关注作者的博客和GitHub。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • [翻译]PyCairo指南裁剪和masking
    裁剪和masking在PyCairo指南的这个部分,我么将讨论裁剪和masking操作。裁剪裁剪就是将图形的绘制限定在一定的区域内。这样做有一些效率的因素࿰ ... [详细]
  • 在一对一直播源码使用过程中,有时会出现软键盘切换闪屏问题,就是当切换表情的时候屏幕会跳动,因此要对一对一直播源码表情面板无缝切换进行优化。 ... [详细]
author-avatar
博客小辈_824
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有