系列文章

前言

在Android布局优化(一)从布局加载原理说起中我们说到了布局加载的两大性能瓶颈,通过IO操作将XML加载到内存中并进行解析和通过反射创建View。这里介绍一种避免运行时通过IO操作读取布局文件的“黑科技”—X2C。个人认为这个技术在实际项目中使用可能会需要处理一些兼容性问题,但是从技术人员的思维发散的角度,我认为这其中的一些思想还是很值得学习和借鉴的

背景

一般大家在写页面时都是通过xml写布局,通过setContentView、或LayoutInflater.from(context).inflate方法将xml布局加载到内存中

优点

可维护性好

支持即时预览

代码结构清晰

缺点

读取xml很耗时

递归解析xml较耗时

反射生成对象的耗时是new的3倍以上

我们团队在这个问题上也探索过很多解决方案,一度走到了另一个极端,完全废弃xml,所有控件通过java来new,甚至直接在canvas里绘制,这样虽然性能确实提升了,但是代码已经没有了一丁点可读性,可维护性。  我们后来反思代码到底是给机器看的,还是给人看的??也许X2C已经给了我们一个答案

X2C

为了即保留xml的优点,又解决它带来的性能问题,我们开发了X2C方案。即在编译生成APK期间,将需要翻译的layout翻译生成对应的java文件,这样对于开发人员来说写布局还是写原来的xml,但对于程序来说,运行时加载的是对应的java文件。     我们采用APT(Annotation Processor Tool)+ JavaPoet技术来完成编译期间【注解】->【解注解】->【翻译xml】->【生成java】整个流程的操作。

性能对比

在开发集成完之后我们做了简单的测试,性能对比如下

加载方式

次数

平均加载时间

XML

100

30

X2C

100

11

集成使用

1.导入依赖

在module的build.gradle文件添加依赖

annotationProcessor 'com.zhangyue.we:x2c-apt:1.1.2'

implementation 'com.zhangyue.we:x2c-lib:1.0.6'

2.添加注解

在使用布局的任意java类或方法添加注解即可

@Xml(layouts = "activity_main")

3.配置自定义属性(没有可不配)

在module下建立X2C_CONFIG.xml文件,里面配置定义属性和方法的映射关系,如果接收者是view,则写view.否则填params.

4.通过X2C加载布局

在原先使用setContentView或inflate的地方替换,如下:

this.setContentView(R.layout.activity_main); --> X2C.setContentView(this, R.layout.activity_main);

LayoutInflater.from(this).inflate(R.layout.activity_main,null); --> X2C.inflate(this,R.layout.activity_main,null);

过程文件

原始的xml

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingLeft="10dp">

android:id="@+id/head"

layout="@layout/head"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true" />

android:id="@+id/ccc"

style="@style/bb"

android:layout_below="@id/head" />

生成的java文件

/**

* WARN!!! dont edit this file

* translate from {@link com.zhangyue.we.x2c.demo.R.layout.activity_main}

* autho chengwei

* email chengwei@zhangyue.com

*/

public class X2C_2131296281_Activity_Main implements IViewCreator {

@Override

public View createView(Context ctx, int layoutId) {

Resources res = ctx.getResources();

RelativeLayout relativeLayout0 = new RelativeLayout(ctx);

relativeLayout0.setPadding((int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,res.getDisplayMetrics())),0,0,0);

View view1 =(View) new X2C_2131296283_Head().createView(ctx,0);

RelativeLayout.LayoutParams layoutParam1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);

view1.setLayoutParams(layoutParam1);

relativeLayout0.addView(view1);

view1.setId(R.id.head);

layoutParam1.addRule(RelativeLayout.CENTER_HORIZONTAL,RelativeLayout.TRUE);

ImageView imageView2 = new ImageView(ctx);

RelativeLayout.LayoutParams layoutParam2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,res.getDisplayMetrics())));

imageView2.setLayoutParams(layoutParam2);

relativeLayout0.addView(imageView2);

imageView2.setId(R.id.ccc);

layoutParam2.addRule(RelativeLayout.BELOW,R.id.head);

return relativeLayout0;

}

}

生成的映射文件

/**

* WARN!!! don't edit this file

*

* author chengwei

* email chengwei@zhangyue.com

*/

public class X2C127_activity implements IViewCreator {

@Override

public View createView(Context context) {

View view = null ;

int sdk = Build.VERSION.SDK_INT;

int orientation = context.getResources().getConfiguration().orientation;

boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE;

if (isLandscape) {

view = new com.zhangyue.we.x2c.layouts.land.X2C127_Activity().createView(context);

} else if (sdk >= 27) {

view = new com.zhangyue.we.x2c.layouts.v27.X2C127_Activity().createView(context);

} else if (sdk >= 21) {

view = new com.zhangyue.we.x2c.layouts.v21.X2C127_Activity().createView(context);

} else {

view = new com.zhangyue.we.x2c.layouts.X2C127_Activity().createView(context);

}

return view;

}

}

不支持

merge标签 ,在编译期间无法确定xml的parent,所以无法支持

系统style,在编译期间只能查到应用的style列表,无法查询系统style,所以只支持应用内style

支持

兼容ButterKnifer

兼容DataBinding

各种系统控件、自定义控件

include标签

viewStub标签

fragment标签

应用style

自定义属性

系统属性

属性名称

属性名称

android:textSize

app:layout_constraintRight_toLeftOf

android:textColor

app:layout_constraintBottom_toTopOf

android:text

app:layout_constraintTop_toTopOf

android:background

app:layout_constrainedHeight

Android布局加载慢,Android布局优化(四)X2C — 提升布局加载速度200%相关推荐

  1. 【Android优化篇】提升Activity加载速度的方法

    文章转自:http://www.jianshu.com/p/2007ca0290d3 作者: CoderFan 前言 这个也是我面试遇到的问题,当时只回答了一种情况,异步加载数据,没想到别的方式,回来 ...

  2. Android开发 第五课 Android的几种布局方式

    通常我们开发的应用程序都是需要具有友好的用户界面,那么Android中提供了哪些布局方式呢?当我们构思好了所需要的各种控件的时候,怎样才能将它们放到Android设备屏幕上正确的位置呢?在Androi ...

  3. AD学习笔记(四)PCB布局分析

    文章目录 AD学习笔记 第四讲 PCB布局分析 一.PCB导入以及常见报错解决方法 二.常见绿色报错的消除 三.PCB板框的评估及叠层设计 四.快捷键设置及推荐 五.PCB布局注意事项 AD学习笔记 ...

  4. Android 系统性能优化(24)--布局优化

    前言 我们知道一个界面的测量和绘制是通过递归来完成的,减少布局的层数就会减少测量和绘制的时间,从而性能就会得到提升.当然这只是布局优化的一方面,那么如何来进行布局的分析和优化呢?本篇文章会给你一个满意 ...

  5. Android 性能优化---(7)布局优化

    Android性能优化:布局优化 详细解析 前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的布局优化,希望你们会喜欢. 目录 1. 影响的性能 布局性能的好坏 主要影响 ...

  6. android布局时长分析,Android性能优化:布局优化 详细解析(含、、讲解 )

    前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的布局优化,希望你们会喜欢. 目录 1. 影响的性能 布局性能的好坏 主要影响 :Android应用中的页面显示速度 2. ...

  7. Android绘制优化(二)布局优化

    相关文章 Android绘制优化(一)绘制性能分析 前言 我们知道一个界面的测量和绘制是通过递归来完成的,减少布局的层数就会减少测量和绘制的时间,从而性能就会得到提升.当然这只是布局优化的一方面,那么 ...

  8. Android:最全面详细的性能优化攻略(含内存优化、内存泄漏、绘制优化、布局优化、图片优化、APK优化、多线程优化、列表优化等)

    前言:佛教中有一句话:初学者的心态,拥有初学者心态是件了不起的事情.真正的大师永远怀有一颗学徒的心. 一.概述 在Android中,性能优化是细分领域中最难且也是知识面涉及最深和最广的方向之一. 更快 ...

  9. android识别手机文件 快速扫描并优化加载速度

    一.最近在做一个需求,手机文件的快速扫描功能. 先附上效果图: 二.这边写了四种类型的文件识别,分别为音视频,图片,文件,并调取手机文件,这边分别用了四个Fragment,方便复制粘贴,用哪个粘哪个, ...

最新文章

  1. LLVM笔记(5) - SMS
  2. BZOJ - 3578: GTY的人类基因组计划2
  3. python 400集大型视频下载_Python400集大型视频,无偿分享,从正确方向学习python...
  4. C:如何分解整数(从末位往前取以及从首位往后取)
  5. AndroidStdio换源
  6. 谷歌octotree插件的使用
  7. 北京大学信科计算机学院教学计划,北京大学信息科学的技术学院.ppt
  8. mysql查询IP地址
  9. Navicat 连接数据库报错:1045-Access denied for user ‘root‘@‘localhos
  10. 服务器不能全屏显示,远程服务器如何全屏显示
  11. 计算机硬盘对考,两个硬盘对拷(硬盘对刻)图文教程
  12. CTF-Anubis HackTheBox 渗透测试(二)
  13. Verilog基础知识
  14. 使用Dubbo实现简单的RPC调用(Spring配置文件版)
  15. wordpress插件_10个最佳WordPress论坛插件(比较)
  16. signature=694cde3d7f2450116894167453553a22,FIDO-U2F-Ledger 注册和登录过程中chrome和后台交互log分析...
  17. CEF 下载文件扩展
  18. java获取扫描枪的数据到数据库
  19. 360度MG996R舵机使用方法
  20. shell处理HBase命令的执行结果

热门文章

  1. java ee api_Java EE安全性API向前发展
  2. 操作方法:带有Thymeleaf和Spring Boot的Java 8日期和时间
  3. spring可用于数据层吗_Spring XD用于数据提取
  4. Java中的装饰器设计模式
  5. Java中的HashSet
  6. Java 11快多少?
  7. 为您的Web应用程序启用两因素身份验证
  8. Vaadin提示:以声明方式构建UI
  9. Java / Web项目中的NPM模块Browser-Sync
  10. cargo maven_用于集成测试的Maven Cargo插件