8年老Android开发谈;简化UI都没弄明白凭什么拿高薪?

this.viewClass = c;
}

public Node(AttributeSetter setter) {
this.setter = setter;
}
}

现在我们需要定义类在产生虚拟布局的时候实际能干的事情了,那就让我们来调用可渲染类吧。一个可渲染类可以是一个 Activity,或者一个自定义的 ViewGroup,或者 Fragment 也凑合。每一个可渲染类都应该有一个用于返回虚拟布局的方法,此外,如果这个方法指定了它将要作用于实际布局中的哪个 View 会更好。

public interface Renderable {
Node view();
ViewGroup getRootView();
}

由于 v() 方法的第一个参数是 View 子类的泛型,所以你不用担心类型安全问题。剩下的参数都是结点类型,所以我们只需要把它们添加到 list 中,无视掉空结点的话效果会更好一些。

public static Node v(final Class<? extends View> cls, final Node …nodes) {
return new Node(cls) ;
}

Here’s an example of the text() attribute setter (the real code is a bit different, but it could have been implemented like this):

下面是一个 text() 属性的设置方法(实际代码会有点不一样,但是也能像下面这样实现):

public static Node text(final String s) {
return new Node(new AttributeSetter() {
public void set(View v) {
((TextView) v).setText(s);
}
});
}

其他类似的工具方法也能用于改变线性布局的方向,View 的大小、页边距、间距,总之所有 View 的参数都能被改变。

那么,我们要怎么去渲染呢?

现在我们需要一个“渲染者”。这是一个能够根据类名创建 View ,使用 AttributeSetters修改对应的参数并且递归地添加子 View的方法。(同样的,下面的代码也是被简化的,实际的代码会有些不一样,主要差别在于当结点没有被改变的时候,我们应该如何避免视图的渲染)

public static View inflateNode(Context c, Node node, ViewGroup parent) {
if (node.viewClass == null) {
throw new RuntimeException(“Root is not a view!”);
}
// Exception handling skipped here to make the code look shorter
View v = (View) node.viewClass.getConstructor(Context.class).newInstance©;
parent.addView(v);
for (Node subnode: node.attrs) {
if (subnode.setter != null) {
subnode.setter.set(v);
} else {
View subview = inflateNode(c, subnode, (ViewGroup) v);
}
}
return v;
}

现在我们真的可以摆脱 XMLS,并以一种简洁的方式通过 Java 进行布局了。

布局结点不应该直接地被使用,而应该是通过 render(Renderer r) 和 render()被使用。前者用于重渲染某一个 View,后者用于重渲染所有被展示的 View。Renderer 通过一个弱哈希表存储,使得在 View 被移除或者 Activity 被销毁的同时 - 他们的渲染者也不会再被使用。

什么时候去渲染呢?

这个框架的核心在于 自动进行重渲染,使得 UI 总能展示当前的虚拟布局状态。这就意味着 render() 应该在某个特定的节点被调用。

我参考 Mithril 的方法,把每一个 On…Listener 和 调用 render 的方法捆绑在每一次 UI 的交互中。

public static Node onClick(final View.OnClickListener listener) {
return new Node(new AttributeSetter() {
public void set(View v) {
v.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
listener.onClick(v);
// After the click was processed - some data may have been changed
// so we try to re-render the UI
render();
}
});
}
});
}

我觉得这样做是有道理的,因为大多数 Android 应用的数据都是在发生用户交互的时候被改变的。如果你的数据是因为其他因素被改变的 - 那就只能手动通过 render()渲染了。

总的来说

这个方法虽然简单,却非常有用:

  • 你能用类似 XML 的方式定义你的布局结构(通过嵌套调用 v() 方法)

  • 你能用一种清晰易懂的方式绑定数据和监听器

  • 布局都是类型安全的,并且你的编译器会自动完成相应的工作

  • 没有运行时产生的开销,没有使用反射机制,没有自动生成代码

  • 你能在任何地方使用 Java(变量,语句,宏)生成布局

  • 你能用自定义 View 和自定义的属性设置方法

  • 因为你的所有 UI 数据都被保存在属性中,因此你能轻易的保存它们

  • 使用纯 Java 实现这些逻辑需要的代码还不到 250 行!

以上证明了这个方法是可行的。现在我在想,如果有人想要用这个方法开发一个功能齐全的库呢?

设计一个好的“区分”算法会是其中的关键。基本地,它应该能判断一个结点是否被添加/移除/修改,而文件就在于属性节点。简单的数据类型我们只要调用 equals() 去比较两个值就可以了,但是监听器呢?

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节

还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

一线互联网面试专题

379页的Android进阶知识大全

379页的Android进阶知识大全

点击:

Android架构视频+BAT面试专题PDF+学习笔记》即可免费获取~

A-1710493660897)]

[外链图片转存中…(img-4shqIqZo-1710493660897)]

点击:

Android架构视频+BAT面试专题PDF+学习笔记》即可免费获取~

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值