内容简介:年假即将结束,这篇文章也算是我自己梳理android知识的最后几篇了。文章中的整体思路是根据《android开发艺术》结合平时开发经验以及网上的资料完成的。内容用的源码都可以在GitHub上的项目中查看到,希望阅读完这篇文章能让你有所收获。在layout文件中创建在Activity的layout布局引入:
年假即将结束,这篇文章也算是我自己梳理android知识的最后几篇了。文章中的整体思路是根据《android开发艺术》结合平时开发经验以及网上的资料完成的。内容用的源码都可以在GitHub上的项目中查看到,希望阅读完这篇文章能让你有所收获。
项目源码
目录
- 布局优化
- 绘制优化
- 内存泄漏优化
- ListView和Bitmap优化
布局优化
- 减少布局文件的层级
- 删除布局中无用的控件和布局
-
尽量使用简单高效的ViewGroup,比如
FrameLayout
和LinaerLayout
- 可以使用include标签复用布局,使用merge标签减少层级
include、merge标签案例
在layout文件中创建 layout/incloude_merge_memory.xml
文件内容如下:
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/mTV_incloud_merge" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/holo_red_light" android:gravity="center" android:padding="5dp" android:text="这是一个include的merge" /> </merge> 复制代码
在Activity的layout布局引入:
<include layout="@layout/incloude_merge_memory" /> 复制代码
ViewStub
- 它是一个轻量级的布局宽度、高度只有0,不参与绘制过程。
- 按需加载,不占用空间。
- 当显示ViewStub中的布局时候,ViewStub会被替换掉,并且会被从布局中移除。
xml代码:
<ViewStub android:id="@+id/mVS_layoutMemory" android:layout_width="match_parent" android:layout_height="80dp" android:background="@android:color/holo_blue_bright" android:inflatedId="@id/mRL_viewStubMemory" android:layout="@layout/viewsutub_memory" android:padding="10dp" /> 复制代码
上面代码中id为mVS_layoutMemory为ViewStub的id,而inflatedId是引入布局 @layout/viewsutub_memory
跟布局的id。需要注意的是ViewStub中layout布局是不支持merge标签的,接下来看一下 java 代码的调用:
mVS_layoutMemory = findViewById(R.id.mVS_layoutMemory); mVS_layoutMemory.setVisibility(View.VISIBLE); 复制代码
绘制优化
- 不要在onDraw中创建新的布局对象
- 不要在onDraw中做大量的耗时操作
内存泄漏优化
- 静态变量引起的泄漏
- 单例模式引起的泄漏
- 非静态内部类持有外部引用导致的泄漏
- Handler引起的内存泄漏
- 属性动画引起的泄漏
静态变量导致的内存泄漏
这种情况常见的是Context的使用,比如我们写了一个 工具 类,里面的静态方法需要用到Context。如果我们将Activity的this传给这个方法,那么Activity在被回收的时候由于这个静态变量持有Activity的引用,导致不能被回收从而引起内存泄漏。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layoyt_memory); AppUtil.getTesLeak(this); } public static void getTesLeak(Context context) { Toast.makeText(context, "您的内存泄漏啦", Toast.LENGTH_SHORT).show(); } 复制代码
解决上面的问题也很多简单,如果我们的工具类不是一定需要Activity的Context,难么我们可以考虑使用 getApplicationContext()
。因为 getApplicationContext()
是和我们App的生命周期一样长,如果App不退出他就不会被回收。
单例模式导致的内存泄漏
单例引起的内存泄漏,大概思路上面差不多,也是因为静态变量的生命周期太长,如果程序不退出,系统就不会对其回收,这将导致本应该不用的对象不能回收,我们可以指定Context为getApplicationContext();来避免内存泄漏。
public class MemorySingle { //如果传入上下文 private static Context context; private MemorySingle() { } public static MemorySingle getInstance(Context context) { //防止内存泄漏 MemorySingle.context = context.getApplicationContext(); return Menory.single; } static class Menory { private static final MemorySingle single = new MemorySingle(); } } 复制代码
非静态内部类持有外部引用引起的泄漏
因为非静态内部类的生命周期是和外部类的生命周期绑定在一起的,非静态内部类会持有外部类的引用,如果我们在内部类中做一些耗时操作,如下面内部类sleepThread()方法让线程睡10秒,在这个时候如果Activy要销毁,但是因为内部类持有外部类的引用,它的sleepThread()方法还没执行完,所以导致Activy不能被回收,引起内存泄漏。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layoyt_memory); TestLeak testLeak = new TestLeak(); testLeak.sleepThread(); } class TestLeak { private void sleepThread() { new Thread(new Runnable() { @Override public void run() { try { //睡10秒 Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } } 复制代码
解决方法将TestLeak改成静态内部类
static class TestLeak { private void sleepThread() { new Thread(new Runnable() { @Override public void run() { try { //睡10秒 Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } 复制代码
Handler引起的内存泄漏
我们使用Handler做消息处理的时候可能不注意会用下面这种写法:
private Handler mHanlder = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 200: mTV_incloud_merge.setText((String) msg.obj); break; } super.handleMessage(msg); } }; 复制代码
上面的mHanlder是Handler的非静态匿名内部类,上面我们提到过非静态匿名内部类会持有外部引用,所以如果使用上面的写法也会引起内存泄漏。下面有两种方式可以避免泄漏。
第一种方式: 使用静态内部类+弱引用方式
static class MyHanlder extends Handler { //弱引用 WeakReference<Activity> mWeakRef; public MyHanlder(Activity activity) { mWeakRef = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 200: LayoutMemoryActivity activity = (LayoutMemoryActivity) mWeakRef.get(); activity.mTV_incloud_merge.setText((String) msg.obj); break; } } } 复制代码
第二种: Handler.Callback方式处理消息
Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 200: mTV_incloud_merge.setText((String) msg.obj); break; } return false; } }) 复制代码
属性动画导致的内存泄漏
当一个Activy中有一个无限循环的属性动画,在Activy销毁的时候没有停止动画也会引起内存泄漏
ObjectAnimator oA = ObjectAnimator.ofFloat(mBnt_layoutMemory, "rotation", 0, 360).setDuration(20000); oA.start(); 复制代码
上面的是一个按钮选装动画,20秒后执行完,如果在动画还为执行完的时候销毁Activy,将会导致Activy无法释放引起内存泄漏。下面是解决办法
@Override protected void onDestroy() { super.onDestroy(); //取消动画 oAnimator.cancel(); } 复制代码
ListView和Bitmap优化
ListView优化
ListView的优化是一个很长见的问题,主要是通过ViewHolder实现对item的复用,这里不做过多的解释了。在这我推荐一篇文章感兴趣的可以看看,下面有一个例子:
@Override public View getView(final int position, View convertView, ViewGroup parent) { MyHolder myHolder = null; //判断是否有缓存布局 if (convertView == null) { convertView =LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, null); myHolder = new MyHolder(convertView); convertView.setTag(position); } else { //得到缓存布局 myHolder = (MyHolder) convertView.getTag(); } myHolder.mTV_test1.setText(textContent); } class MyHolder { TextView mTV_test1; MyHolder(View view) { mTV_test1 = view.findViewById(android.R.id.text1); } } 复制代码
Bitmap优化
我们大部分图片处理是使用 glide
、'picasso',这些框架在图片加载速度和性能优化方面已经很好了,但有些特殊情况可能需要我们自己实现图片的处理,主要注意下面几个方面。
- 对图片进行压缩
- 缓存策略
- 图片不使用的时候要记得释放
总结
android的性能优化需要了解的方面还有很多比如电量的优化、包大小、启动速度的优化等等,上面列出的只是一部分常见的问题和解决办法。在开发过程中需要优化的放要远比上面写道的多,还需要我们自己多积累经验和结合实际考虑来优化。
参考
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Mesos 1.5 发布,在存储、性能资源管理方面有重大改进
- Python--Redis实战:第四章:数据安全与性能保障:第8节:关于性能方面的注意事项
- O2OA 稳定版 V4.2235 发布,功能性能等多方面优化升级
- 大数据方面核心技术有哪些?
- 推荐一些学习方面的公众号
- 滴滴开源 移动开发 方面的 4 个项目
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
设计模式
[美] Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides / 李英军、马晓星、蔡敏、刘建中 等 / 机械工业出版社 / 2000-9 / 35.00元
这本书结合设计实作例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。书中分类描述了一组设计良好、表达清楚的软件设计模式,这些模式在实用环境下特别有用。此书适合大学计算机专业的学生、研究生及相关人员参考。 书中涉及的设计模式并不描述新的或未经证实的设计,只收录了那些在不同系统中多次使用过的成功设计。一起来看看 《设计模式》 这本书的介绍吧!