8年老Android开发谈;简化UI都没弄明白凭什么拿高薪?,安卓移动开发基础案例教程

本文介绍了一种使用Java代码动态创建和管理布局的方法,通过构建虚拟布局树,利用接口和类实现属性设置和视图渲染。这种方法允许在运行时改变UI,无需XML布局文件。文中展示了如何创建节点、属性设置器、以及如何根据节点信息实际渲染视图。点击事件处理也与渲染过程相结合,确保数据变化时自动更新UI。
摘要由CSDN通过智能技术生成

v(LinearLayout.class,
orientation(LinearLayout.VERTICAL),
v(TextView.class,
text(someText)),
v(Button.class,
text(“Click me”),
onClick(someClickHandler)));

第一个 v() 方法返回了一个虚拟布局,每一次调用后它会返回当前应用状态的实际展示(不是实际的 View!)

当一些文字变量被改变 - 虚拟树会获得一个被用于下次渲染的发生了改变的结点值,然后调用 setText()改变相应的 TextView 实例。但是其余的布局不会发生任何变化。

一棵虚拟布局树在理想情况下应该只是一个类,我们就把它叫作结点吧。但是结点主要有两种类型:View 结点(TextView.class等等)和属性设置结点,例如text(someText)

那这就意味着结点应该任意包含一个 View 类和一个方法去改变 View 的属性。

interface AttributeSetter {
public void set(View v);
}

public static class Node {
List attrs = new ArrayList();
Class<? extends View> viewClass; // for view nodes
AttributeSetter setter; // for attribute setter nodes

public Node(Class<? extends View> c) {
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程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料,免费分享给大家,希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

毕竟不管遇到什么样的面试官,去面试首先最主要的就是自己的实力,只要实力够硬,技术够强,就不怕面试拿不到offer!

想要面试顺通嘛,赶紧领取下面的面试资料为之后的面试做足准备叭!这里提前祝各位面试成功!

资料领取方式:  Android架构设计

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!希望读到这的您能点个小赞和关注下我,以后还会更新技术干货,谢谢您的支持!

[外链图片转存中…(img-hdoRtfhx-1646470224787)]

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!希望读到这的您能点个小赞和关注下我,以后还会更新技术干货,谢谢您的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值