登录 立即注册
安币:

查看: 632|回复: 8

提升Android布局加载速度200%

[复制链接]

19

主题

781

帖子

3416

安币

码皇(巴士元老)

Rank: 8Rank: 8

发表于 2018-9-18 22:11:58 | 显示全部楼层 |阅读模式

[i=s] 本帖最后由 葫芦妹1987 于 2018-9-19 23:49 编辑 [/i]

背景

 一般大家在写页面时都是通过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.0'  
implementation 'com.zhangyue.we:x2c-lib:1.0.6'  

2.添加注解

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

@Xml(layouts = "activity_main")  

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

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

<x2c-config>  
    <attr name="app:mixColor" toFunc="view.setMixColor(int)" />  
    <attr name="android:layout_marginTop" toFunc="params.topMargin=int" />  
</x2c-config>  

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

  `xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    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">

    <include
        android:id="@+id/head"
        layout="@layout/head"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" />

    <ImageView
        android:id="@+id/ccc"
        style="@style/bb"
        android:layout_below="@id/head" />
</RelativeLayout>


#### 生成的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;
  }
}

#### 生成的映射文件  

/**

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标签(感谢[Dreamskya]([https://github.com/Dreamskya](https://github.com/Dreamskya)))提出宝贵意见  
* 应用style  
* 自定义属性(感谢[Anzhi-Meiying]([https://github.com/Anzhi-Meiying](https://github.com/Anzhi-Meiying))提出的宝贵意见)  
* 系统属性  

| 属性名称|属性名称|  
| ------ |------- |  
|android:textSize| app:layout_constraintRight_toLeftOf|  
|android:textColor| app:layout_constraintBottom_toTopOf|  
|android:text| app:layout_constraintTop_toTopOf|  
|android:background| app:layout_constrainedHeight|  
|[查看全部](supportAll.md)|  

# 源码  

475

主题

1023

帖子

5809

安币

手工艺人

发表于 2018-9-19 11:37:00 | 显示全部楼层
感谢分享,安卓巴士有你更精彩:lol

3

主题

7060

帖子

1756

安币

Android大神

Rank: 6Rank: 6

发表于 2018-9-19 11:39:11 | 显示全部楼层
楼主威武,以后多发干货,多办活动~!

2

主题

9497

帖子

2101

安币

Android大神

Rank: 6Rank: 6

QQ达人

发表于 2018-9-19 11:46:16 | 显示全部楼层
安卓巴士是个不错的网站,我来顶个贴~

9

主题

9442

帖子

1794

安币

Android大神

Rank: 6Rank: 6

发表于 2018-9-19 11:49:38 | 显示全部楼层
感谢大神~

9

主题

9316

帖子

1827

安币

Android大神

Rank: 6Rank: 6

QQ达人

发表于 2018-9-19 12:08:46 | 显示全部楼层
感谢大神~

0

主题

9064

帖子

2393

安币

Android大神

Rank: 6Rank: 6

发表于 2018-9-19 12:13:58 | 显示全部楼层
楼主威武,以后多发干货,多办活动~!

1

主题

76

帖子

1277

安币

Android大神

Rank: 6Rank: 6

发表于 2018-10-3 11:45:22 | 显示全部楼层
感谢分享,安卓巴士有你更精彩:)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区
联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| 下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表