【Android】性能实践—编码优化与布局优化学习笔记

news2024/11/15 12:45:28

【Android】性能实践—编码优化与布局优化学习笔记

编码优化

使用场景

  1. 如果需要拼接字符串,优先使用StringBuffer和StringBuilder进行凭借,他们的性能优于直接用加号进行拼接,因为使用加号连接符会创建多余的对象
  2. 一般情况下使用基本数据类来代替封装数据类型(比如int优于Integer)
  3. 当返回一个String类型的数据时,如果明确知道返回后的字符串用于进行拼接操作,那么可以考虑返回StringBuffer,因为StringBuffer是一个对象的引用而String的话就是创建了一个短生命周期的临时对象
  4. 类似于第二条,基本数据类型数组也优于对象数据类型数组(a[]和b[]使用起来效率比c(a, b)[]高得多)

静态优于抽象

当我们只想调用某个对象的某个方法去实现一个功能的时候,可以将该方法设置为静态方法,因为调用静态方法可以不用创建对象,也可以使得调用速度提升。

class Utils {
    public static int add(int a, int b) {
        return a + b;
    }
}

// 调用静态方法,不需要创建 Utils 的对象
int result = Utils.add(3, 5);

使用static和final修饰符

内存效率

  • static 关键字使变量成为类变量,而不是实例变量。这样,不管创建多少个类的实例,常量在内存中只存在一份,节省内存空间。
public class MyClass {
    public static final int MAX_VALUE = 100;
}

不可变性

  • final 关键字使变量成为常量,一旦赋值后不能改变。这确保了常量的值不会被意外修改,从而提高了代码的安全性和可靠性。
public class MyClass {
    public static final int MAX_VALUE = 100;
}

全局访问

  • static 使得常量可以通过类名直接访问,无需创建类的实例,方便全局使用。
int maxValue = MyClass.MAX_VALUE;

编译期常量

  • static final 常量在编译时就被确定,因此在编译期可以进行优化,比如内联(在使用常量的地方直接替换为常量值)。
public class MyClass {
    public static final int MAX_VALUE = 100;
}
// 在其他地方使用时
int value = MyClass.MAX_VALUE;  // 编译时会直接替换为 100

使用增强型for循环

有三个循环方式:

static class Counter {
    int mCount;
}
 
Counter[] mArray = ...
 
public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mCount;
    }
}
 
public void one() {
    int sum = 0;
    Counter[] localArray = mArray;
    int len = localArray.length;
    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mCount;
    }
}
 
public void two() {
    int sum = 0;
    for (Counter a : mArray) {
        sum += a.mCount;
    }
}

首先,zero()方法是最慢的一种,因为循环的判断条件为 i < mArray.length ,也就是说在每一层循环进行判断时都要重新计算一遍mArray的长度

其次,one()方法相对第一种就快了很多,它直接在循环前就用len保存了长度,不用每层遍历都再计算一遍

two()方法在没有JIT(Just In Time Compiler)的设备上是运行最快的,而在有JIT的设备上运行效率和one()方法不相上下

“JIT” 指的是 “Just-In-Time” 编译,它是一种动态编译技术,用于提高 Java 程序的执行效率。JIT 编译器在 Java 虚拟机(JVM)运行时将字节码编译成本地机器码,从而加快程序的执行速度。

JIT 编译的工作原理

  1. 解释执行
    • 初始阶段,Java 程序的字节码由 JVM 的解释器逐行解释执行。解释执行通常较慢,但不需要编译阶段的开销。
  2. 热点代码检测
    • JVM 会监控代码的执行情况,识别那些频繁执行的代码段,这些代码段被称为“热点代码”。
  3. 编译为机器码
    • 一旦某段代码被识别为热点代码,JIT 编译器会将这段字节码编译成机器码,生成本地可执行代码,从而提高运行速度。
  4. 优化
    • JIT 编译器还会对热点代码进行各种优化,如内联、循环展开、常量折叠等,以进一步提高性能。
  5. 缓存和重用
    • 编译后的机器码会被缓存,以便后续的调用可以直接使用这些优化后的代码,避免重复编译。

使用封装好的API

Java语言当中其实给我们提供了非常丰富的API接口,我们如果能使用系统提供的API就尽量使用,因为系统的API基本上比我们自己写的代码要快得多,它们的很多功能都是通过底层的汇编模式执行的。

避免在内部调用Getters/Setters方法

下面一个例子:

public class Calculate {
	
	private int one = 1;
	
	private int two = 2;
 
	public int getOne() {
		return one;
	}
 
	public int getTwo() {
		return two;
	}
	
	public int getSum() {
		return getOne() + getTwo();
	}
}

就属于在内部调用getters/setters方法

但其实我们在类的内部可以直接使用类中的封装字段:

public int getSum() {
	return one + two;
}

布局优化

重用布局文件

<include>的使用

目前几乎所有的软件都会有一个头布局,这个头布局是在所有界面都要使用,但是如果在每个界面都写一次那就太麻烦了,我们可以新建一个布局专门表示头布局,当其他界面要使用的时候直接使用<include>调用就可以了

假设我们随便建了一个头布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    android:background="#EEEEEE">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginStart="8dp"
        android:text="HaHa"
        android:textColor="#00dddd"
        android:textSize="20sp" />
</LinearLayout>

当我们在其他界面要使用的时候就可以直接调用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/header"/>


</LinearLayout>

但是如果我们本来的界面中还有别的东西,我们在引入header后所有的东西都有可能被覆盖,出现这个问题是原因是因为header的最外层布局是一个宽高都是match_parent的LinearLayout,我们可以将LinearLayout的layout_height属性修改成wrap_content就可以了,但是这种操作会影响header的界面,如何你只希望让activity_main.xml这一个界面受影响的话,那么可以使用覆写<include>属性的方式

<merge>的使用

<merge> 是 Android 布局文件中的一个特殊标签,用于优化布局结构。它的主要目的是减少布局层级,使布局文件更加高效。<merge> 标签不会创建一个新的视图层级,而是将其子视图直接合并到包含它的布局中。

使用 <merge> 标签的场景:

  1. 优化布局层级:
    • 当你有一个布局文件(如包含多个子视图的布局)需要嵌套在其他布局中时,使用 <merge> 标签可以避免多余的布局层级,从而提高渲染性能。
  2. 简化布局结构:
    • 避免不必要的嵌套布局,减少布局的复杂度和绘制开销。

假设有一个复杂的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Click Me" />
    </LinearLayout>

    <!-- 其他视图 -->
</LinearLayout>

这个布局的嵌套关系如图:

在这里插入图片描述

可以使用merge对布局进行优化:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include
        layout="@layout/optimized_sub_layout" />

    <!-- 其他视图 -->
</LinearLayout>

optimized_sub_layout.xml 中使用 <merge> 标签:

<!-- res/layout/optimized_sub_layout.xml -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />
</merge>

优化后布局变成了

在这里插入图片描述

参考博客:Android最佳性能实践(三)——高性能编码优化_android 硬编码 节省码率-CSDN博客

Android最佳性能实践(四)——布局优化技巧_android中对布局进行优化-CSDN博客


已经到底啦!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1945018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有监督学习基础

基本概念 给定输入有为&#xff08;x,y&#xff09;&#xff0c;其中x表示学习特征&#xff0c;y表示输出&#xff0c;m表示输入总数&#xff0c;有监督学习旨在根据输入建立能够预测可能输出的模型&#xff0c;大致可以分为回归和分类两种&#xff0c;代表可能输出是无限的或…

vue 实战 tab标签页+el-card+流式布局+异步接口调用

<template><div><!-- 布局按钮 --><el-button click"dialogVisible true">布局配置查看</el-button><!-- 布局配置对话框 --><el-dialog :visible.sync"dialogVisible" title"布局配置查看" width"…

nature reviews genetics | 单细胞基因组eQTL发展历程

– https://doi.org/10.1038/s41576-023-00599-5 留意更多内容&#xff0c;欢迎关注微信公众号&#xff1a;组学之心 Single-cell genomics meets human genetics 单细胞基因组技术已经扩展到可以检测数千个个体的样本的程度。将大规模的单细胞信息与基因型数据相结合&#x…

STM32F103C8T6基于YMODEM协议的串口IAP升级实践

一.为什么要做IAP升级 1.不易拆卸的设备&#xff0c;可以使用IAP升级&#xff0c;方便用户升级固件 2.YMODEM协议是串口传输协议&#xff0c;传输速率较高&#xff0c;传输文件较大时&#xff0c;传输时间较短 3.不想给别人源代码&#xff0c;但是项目有bug&#xff0c;需要修…

【PLC】三菱FX3U下载程序通讯中断问题解决方法之一

博主最近买了一个三菱PLC FX3U&#xff0c;然后随意在GX Works中编写了一段带有子程序的程序&#xff0c;后来发现刷写程序过程中&#xff0c;会突然出现通讯中断的情况&#xff0c;然后切断PLC电源&#xff0c;变更COM口&#xff0c;重启PLC后&#xff0c;通讯才可以连接上&am…

鸿蒙OpenHarmony Native API【drawing_pen.h】 头文件

drawing_pen.h Overview Related Modules: [Drawing] Description: 文件中定义了与画笔相关的功能函数 Since: 8 Version: 1.0 Summary Enumerations Enumeration NameDescription[OH_Drawing_PenLineCapStyle] { [LINE_FLAT_CAP], [LINE_SQUARE_CAP], [LINE_ROUND_…

PMP考试难度大吗?

由于目前的PMP考试主要以新大纲为主&#xff0c;许多内容都已经发生了变化&#xff0c;因此学习新内容以适应这些变化仍然是非常必要的。 一、新版考试题量和答题时间有何变化&#xff1f; 题量由200道减少到180道&#xff0c;因此答题时间相对更充裕。 二、新版考试的整体难…

洛谷 P1035 [NOIP2002 普及组] 级数求和 题解

思路1&#xff08;68分&#xff0c;测3&#xff0c;测5TLE&#xff09; &#xff1a; #include<bits/stdc.h> using namespace std; int a[100005]; int main() {int k,i;cin >> k;for(i1;;i){double sum0;//要在这里初始化for(int j1;j<i;j){double s1*1.0/j;…

php接口返回的json字符串,json_decode()失败,原来是多了红点

问题&#xff1a; 调用某个接口返回的json&#xff0c;json_decode()失败&#xff0c;返回数据为null&#xff0c; echo json_last_error();返回错误码 4 经过多次调试发现&#xff1a;多出来一个红点&#xff0c;预览是看不到的。 解决&#xff1a;要去除BOM头部 $resul…

Pytorch transforms 的研究

绝对路径与相对路径差别 transforms的使用 from torchvision import transforms from PIL import Imageimg_path "dataset/train/bees/16838648_415acd9e3f.jpg" img Image.open(img_path) tensor_trans transforms.ToTensor() tensor_img tensor_trans(img) prin…

优选算法之二分查找(上)

目录 一、二分查找 1.题目链接&#xff1a;704. 二分查找 2.题目描述&#xff1a; 3.算法流程&#xff1a; 4.算法代码&#xff1a; 二、在排序数组中查找元素的第一个和最后一个位置 1.题目链接&#xff1a;34. 在排序数组中查找元素的第一个和最后一个位置 2.题目描述…

防爆智能手机如何助力电气行业保驾护航?

在电气行业的智能化转型浪潮中&#xff0c;防爆智能手机以其强大的数据处理能力、实时通讯功能及高度集成的安全特性&#xff0c;正成为保障电力网络稳定运行、预防安全隐患的得力助手。 防爆智能手机在电气行业中发挥着重要的保驾护航作用&#xff0c;主要体现在以下几个方面&…

【性能测试-登录时密码加密存储如何传参】

目的】 登录接口&#xff0c;密码加密传输&#xff0c;开发不做处理的情况下&#xff0c;密码如何加密传输 【方案】 使用前置处理器&#xff1a;JSR223 预处理程序&#xff0c;主要是在执行登录接口前将密码按照加密算法获得对应的加密密码&#xff0c;并传入接口 【说明】前…

天工Godwork AT 5.2.6 GodWork2D 2.1.5 GodWork EOS 2.1实景三维建模软件

天工Godwork AT 5.2.6/GodWork2D 2.1.5/GodWork EOS 2.1实景三维建模软件 获取安装包联系邮箱:2895356150qq.com 本介绍用于学习使用&#xff0c;如有侵权请您联系删除&#xff01; 1.自主研发的平差技术&#xff0c;平差模块不依赖PATB、Bingo等国外技术 2.采用特征匹配&…

系统架构师考点--设计模式

大家好。今天来总结一下设计模式的相关考点。这部分考点也有可能在论文中出现&#xff0c;这里总结的可能不够全面&#xff0c;大家自己可以翻一下教材好好了解一下。 架构模式&#xff1a;软件设计中的高层决策&#xff0c;例如C/S结构就属于架构模式&#xff0c;架构模式反…

【第5章】Spring Cloud之Nacos服务注册和服务发现

文章目录 前言一、提供者1. 引入依赖2.配置 Nacos Server 地址3. 开启服务注册 二、消费者1. 引入依赖2.配置 Nacos Server 地址3. 开启服务注册 三、服务列表四、服务发现1. 获取服务列表2. 测试2.1 获取所有服务2.2 根据服务名获取服务信息 五、更多配置项总结 前言 本节通过…

mysql对数据库的增删改

目录 DML语句&#xff1a; 增加数据&#xff08;insert语句&#xff09; 增加数据&#xff08;insert into select&#xff09; 修改数据&#xff08;update语句&#xff09; 【where 子句条件】 删除数据&#xff08;delete语句&#xff09; 删除数据&#xff08;trunca…

内网隧道——Earthworm(EW)

文章目录 一、EW介绍二、一层网络2.1 一层正向代理2.2 一层反向代理 三、两层网络3.1 二层正向代理3.2 二层反向代理 一、EW介绍 下载地址&#xff1a;EW 常用的命令格式&#xff1a; 参数作用Ssocksd正向代理Rcsock反向代理客户端Rssocks反向代理服务端Lcx_slave一侧通过反弹…

基于SpringBoot的矩形范围面时空分析-以震中附近历史地震为例

目录 前言 1、分析的必要性 2、分析的紧迫性 一、数据库物理模型及空间分析实现 1、数据库物理模型 2、空间数据库中的空间查询分析 二、Java后台程序开发 1、模型层设计 2、业务层的设计与实现 三、WebGIS功能设计与实现 1、同时展示4幅地图 2、初始化地图 3、展示…

算法日记day 18(二叉树的所有路径|左叶子之和)

一、二叉树的所有路径 题目&#xff1a; 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5] 输出&#xff1a;["1->…