随着Android应用增多,功能越来越复杂,布局也越来越丰富了,而这些也成为了阻碍一个应用流畅运行,因此,对复杂的功能进行性能优化是创造高质量应用的基础,本章节将为大家展示几种性能优化的方法,帮助开发者快速的构建运行速度快,相应速度快的应用程序。
< include>标签重用,首先编写common_ui.xml文件:
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="this is a common ui"
android:textSize="30sp" />
接着在主布局中引用:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/common_ui"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
RelativeLayout>
这样,common_ui就被引用了,其中include标签里面属性会覆盖common_ui里面的属性。
使用< ViewStub>实现View的延迟加载,< ViewStub>是个轻量级的组件,它不仅不可视,而且大小为0,首先编写not_often_use.xml文件。
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="not often use"
android:textSize="30sp" />
RelativeLayout>
接着在主布局中引用:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewStub
android:id="@+id/not_often_use"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/not_often_use" />
RelativeLayout>
这个时候是在布局中见不到这个ViewStub的布局的,有两种方法可以来重新显示这个View:
- VISBLE
ViewStub mViewStub = (ViewStub) findViewById(R.id.not_often_use);
mViewStub.setVisibility(View.VISIBLE);
ViewStub mViewStub = (ViewStub) findViewById(R.id.not_often_use);
View inflateView = mViewStub.inflate();
这两种方法唯一区别:
inflate()方法可以返回引用布局,从而可以通过View.findViewById()方法找到相对应控件。
< ViewStub>标签与设置View.GONE有什么区别:
它们的共同点就是在初始化时不会显示,但是< ViewStub>标签只会在显示时,才会去渲染整个布局,而View.GONE在初始化布局树的时候就已经添加在布局树上了,相比之下,< ViewStub>标签的布局具有更高的效率。
由于Android的沙箱机制,每个应用所分配的内存大小是有限度的,内存太低就会触发LMK:Low Memory Killer机制,我们所说的内存是指手机的RAM,它包括以下几个部分:
寄存器(Registers)
速度最快的存储场所,因为寄存器位于处理器内部,在程序中无法控制
- 栈(Stack)
存放基本类型的数据和对象的引用,但对像本身不存放在栈中,而是存放在堆中。
- 堆(Heap)
堆内存用来存放由new创建的对象和数组,在堆中分配的内存,由Java虚拟机的自动垃圾回收(GC)来管理。
- 静态存储区域(Static Field)
静态存储区域就是指在固定的位置存放应用程序运行时一直存在的数据,Java在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态的数据变量。
- 常量池(Constant Pool)
JVM虚拟机必须为每个被装载的类型维护一个常量池,常量池就是该类型所用到常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段和方法的符号引用。
这些概念中最容易搞错的是堆和栈的区分:
- 栈:当定义一个变量时,栈会为该变量分配内存空间,当该变量作用域结束后,这部分内存控件会被用作新的空间进行分配。
- 堆:使用new的方式创建一个变量,那么就会在堆中为这个对象分配内存控件,即使该对象的作用域结束,这部分内存也不会立即被回收,而是等待系统的GC进行回收。
我们可以通过代码分析Heap中的内存状态:
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
int heapSize = manager.getLargeMemoryClass();
系统内存监视服务,通过”Setting-Developer-options-Process Stats”来开启这个功能,也可以使用Dumpsys命令来获取这些信息:
adb shell dumpsys procstats
内存监视工具,通过”Settings-Apps-Running”中打开这个界面,也可以使用Dumpsys命令来获取这些信息:
adb shell dumpsys meminfo
Android Lint工具是Android Studio中集成的一个Android代码提示工具。
Lint的功能非常的强大,大家应该养成写完代码之后检查lint的习惯,这不仅可以让我们及时的发现一些隐藏的问题,而且,更让我们养成良好的代码风格。
Memory Monitor工具是Android studio上的一个内存监视工具,他可以很好的帮助我们进行内存实时分析,通过点击Android studio右下角的Memory Monitor标签就可以进行查看了。
TraceView是一个Android下的可视化性能调查工具,用来分析TraceView日志。
通过代码生成精准范围的TraceView日志:
- 通过调用Debug.startMethodTracing()方法开启监听,调用Debug.stopMethodTracing()方法结束监听,通常会在onCreate时开启监听,在onDestroy时结束监听。
- TraceView日志将会保存到”/sdcard/dmtrace.trace”目录下,因此需要在权限中增加:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
当然除了默认输出日志名,还可以自定义路径和日志名,最后通过ADB命令,将日志文件导出到本地:
adb pull /sdcard/trace_log.trace/local/LOG/
通过Android Device Monitor生成TraceView日志:
- 打开Android Device Monitor工具,选择要调试的进程,点击工具栏中的”start method profiling”按钮,打开,再次点击”start method profiling”按钮即可结束
- TraceView提供两种监听方式:
- 整体监听:跟踪每个方法执行的全部过程,这种方式资源消耗比较大
- 抽样监听:按照指定的频率来进行抽样调查,这种方式需要执行较长时间来获取较精准的样本数据
MAT工具是一个分析内存的强力助手。
打开Android Device Monitor工具,选择要监听的线程,并点击菜单栏中的”Update Heap”按钮。
在Heap标签中点击”Cause GC”按钮,就会显示当前内存状态。
这里有一 个判断当前是否存在内存泄漏的小技巧:当我们不停地点击”Cause GC”按钮的时,如果”data object”一栏中的”Total size”有明显变化,就代表可能存在内存泄漏。
上面是手动查看Heap状态,下面点击菜单栏的”Dump HPROF File”按钮。
系统会生成一个.hprof文件,默认名为包名.hprof,不过还不能直接使用MAT工具查看,还需要进行格式转换,在SDK目录的platform-tools目录下,使用hprof-conv工具帮助转换,命令如下:
D:\sdk\platform-tools>hprof-conv F:\Heap\com.handsome.heap.hprof heap.hprof
格式命令:”hprof-conv infile outfile”生成heap.hprof文件利用MAT工具就可以进行内存分析。
打开MAT工具,选择”Open a Heap Dump”选项,进入分析:
- Histogram
- Histogram直方图,用于显示内存中每个对象的数量、大小和名称
- 在选择对象上单击鼠标右键,在弹出的快捷菜单中选择”List objects-with incoming references”选项查看具体的对象
- Dominator Tree
- Dominator Tree支配树会将内存中的对象按照大小进行排序,并显示对象之间的引用结构
- 对象已经按照”Retained Heap”进行排序了,即按照对象及其持有的引用的内存总和进行排序,通过分析内存占用大的对象找出内存消耗的原因
进入我的CSDN戳这里(我的博客导航)