众所周知,android设备作为一种移动设备,不管是cpu还是内存都无法跟pc设备相提并论。这就意味着我们不能无限制地使用内存和cpu的资源,过多地使用内存会导致oom,过多地使用cpu资源,做大量的耗时任务,会导致手机变得异常卡顿,甚至无法响应出现ANR。所以我们在平常做开发时,一定要注意性能优化的问题,养成良好的编码习惯才会成为优秀的程序员。
话不多说,我将介绍以下几种优化方案
目录
(1)布局优化
布局优化的核心思想减少布局的层级,这样会减少android绘制时的工作量。
如何进行布局优化?
(a)如果布局既可以使用Linearlayout和Relativelayout,建议选择Linearlayout;
如果我们要实现嵌套布局时,建议采用Relativelayout。
(b)采用标签来优化布局
<include>标签
作用 用于布局的重用。
应用场景:下图是我们开发中经常使用到的一个顶部标题栏(当然我已经对此进行过了封装)
我们很多页面都需使用到,所以这里要进行布局的重用,这样不仅减少了大量的代码量,同时也提高了绘制的性能。
使用如下
<?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"
tools:context=".Activity.ChangePwdActivity">
<include layout="@layout/title_layout"/>
</RelativeLayout>
<merge>标签
<merge/>多用于替换FrameLayout或者当一个布局包含另一个时,<merge/>标签消除视图层次结构中多余的视图组。例如你 的主布局文件是垂直布局,include引入了一个垂直布局,这时如果include布局使用的LinearLayout就没意义了,而且会减慢ui 的绘制速度。
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/add"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/delete"/>
</merge>
<ViewStub>标签
ViewStub的意义在于按需加载所需的布局文件,实例开发中,比如网络异常时的界面,这个时候没有必须在整个界面初始化 的时候加载进来,通过ViewStub可以做到使用的时候再加载进来,提高了程序初始化的性能。
使用如下:
<ViewStub
android:id="@+id/stub"
android:inflatedId="@+id/stub_layout"
android:layout="@layout/title_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
android:inflateId:重写ViewStub的父布局控件的Id;android:layout:设置ViewStub被inflate的布局。
加载如下:
//当你想加载布局时,可以使用下面其中一种方法:
((ViewStub) findViewById(R.id.stub)).setVisibility(View.VISIBLE);
// or
View importStub = ((ViewStub) findViewById(R.id.stub)).inflate();
目前ViewStub不支持<merge>标签,且ViewStub的inflate只能执行一次,显示了之后,就不能再使用ViewStub控制它了。
(2)绘制优化
绘制优化的核心思想减少view在ondraw方法里执行大量的操作。
绘制优化记住两点:onDraw方法里不要创建新的局部对象,onDraw方法里不要做耗时操作,也不要执行成千上万次的循环。因为
ondraw方法都是频繁调用的,会占用系统很大的一部分内存,所以在我们实现自定义view的时候,一定要仔细检查onDraw()里的代码。
(3)内存泄露优化
首先内存泄露是什么?简而言之:内存泄露就是长生命周期的对象持有短生命周期的引用,gc不能及时回收。
这里推荐一篇文章 java内存泄露
这里我就只介绍一种 静态变量导致内存泄露的问题
下面的代码将导致activity不能正常销毁,因为mcontent应用了它,虽说这种错误大家都不会犯,但我们还是得重视。
public class Main2Activity extends AppCompatActivity {
private static Context mcontext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mcontext = this;
}
}
(4)线程优化
作为初级程序员,比如说我,之前在做主线程里做耗时操作时基本都是创建一个thread对象,这种确实简单,但也是有弊端的,我们不
可能无限制地创建线程,这样可能会将系统的资源耗尽,严重的话会造成系统崩溃。
所以java引入了线程池的概念,线程池的好处:
线程池内可以重用线程,避免线程的创建和销毁所带来的性能开销;
线程池可以控制并发数,避免大量的线程因抢占系统资源导致阻塞现象的发生。
具体线程池的讲解我不过多介绍,自行Google,有些博客上介绍的非常详细。
总结
关于Android的性能优化我今天只能介绍到这里,更多的优化方式还是需要大家今后在学习中探索。
本文参考:《android开发艺术探索》