Android内存优化

一、内存泄漏

1、什么是内存泄漏

内存泄漏指在程序运行过程中分配的内存空间没有及时释放,导致内存空间占用过多,造成程序的崩溃或者系统的崩溃的现象。一般体现为App启动后,内存不断增加,操作时间越长,内存越大,容易造成ANR或者崩溃。

2、常见的内存泄漏场景

a.静态变量被持有:

“`
public class Singleton{
private static Singleton instance;
public static Singleton getInstance(){
if(instance ==null){
instance =new Singleton();
}
return instance;
}
//…
}
“`

在单例模式中,只要有一个对象持有了该类的引用,那么这个对象和其中的所有成员信息都不会被回收,从而引发了内存泄漏。

b.handler引起内存泄漏:

“`
public class MainActivity extends Activity{
private Handler mHandler =new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
//…
}
“`

在Activity中使用了handler,由于handler持有外部类Activity的引用,那么当Activity被摧毁时,由于handler还持有Acitivity的引用,会导致Activity无法被回收。此时,建议在Activity退出时清除handler的消息队列。

c.监听器泄漏:

“`
public class MainActivity extends Activity{
private MyOnClickListener mListener =new MyOnClickListener(){

@Override
public void onClick(View view) {

}
};
//…

@Override
protected void onDestroy() {
super.onDestroy();
mButton.setOnClickListener(null);
}
}
“`

在Activity中使用监听器时,如果不及时销毁,会造成Activity的内存泄漏,同样的,在Activity销毁时,需要及时清除持有监听器的引用。

二、Bitmap优化

1、Bitmap内存计算

Bitmap在内存中占用的大小=图片的宽度*图片的高度*每个像素点的字节数。

2、Bitmap内存优化

a.采样率缩放

“`
public static Bitmap decodeSampledBitmapFromFile(String filename,int width,int height){
final BitmapFactory.Options options =new BitmapFactory.Options();
options.inJustDecodeBounds =true;
BitmapFactory.decodeFile(filename,options);
options.inSampleSize =calculateInSampleSize(options,width,height);
options.inJustDecodeBounds =false;
return BitmapFactory.decodeFile(filename,options);
}

public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
final int height =options.outHeight;
final int width =options.outWidth;
int inSampleSize =1;

if(height> reqHeight|| width >reqWidth ){
final int heightRatio =Math.round((float)height/ (float)reqHeight);
final int widthRatio =Math.round((float)width/ (float)reqWidth);
inSampleSize =heightRatio<widthRatio? heightRatio:widthRatio;
}
return inSampleSize;
}
“`

b.使用软引用和弱引用

“`
public HashMap<String, SoftReference> imageCache =new HashMap<String, SoftReference>();

//…

SoftReference reference = new SoftReference(bitmap);

imageCache.put(url, reference);
“`

c.LruCache

“`
public class MemoryCache extends LruCache {

public MemoryCache(int maxSize) {
super(maxSize);
}

@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
}

@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
super.entryRemoved(evicted, key, oldValue, newValue);
//释放oldValue的内存空间
oldValue.recycle();
}
}

//…

int maxMemory = (int)(Runtime.getRuntime().maxMemory()/1024);
int cacheSize =maxMemory/8;

mMemoryCache =new MemoryCache(cacheSize);
“`

三、布局优化

1、Layout XML的优化

a.使用include标签

“`

“`

b.使用RelativeLayout,减少deep-level嵌套

“`

“`

c.不使用过于复杂的布局文件

2、代码布局优化

a.手动布局时,减少measure和layout的操作次数

“`
private LinearLayout layoutExample;
layoutExample.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
layoutExample.setOrientation(LinearLayout.VERTICAL);

TextView textView=new TextView(context);
textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
textView.setText(“Custom Text”);

layoutExample.addView(textView);

setContentView(layoutExample);
“`

b.使用自定义View,复用已有的控件

四、资源文件优化

1、资源文件分类

将资源文件按不同的类型进行分类,方便开发和维护。

2、资源文件压缩

a.使用lint工具

打开Android Studio中的预编译检查功能,可检测和提示不必要的资源文件,方便开发时的及时优化。

b.使用TinyPNG或者PngQuant工具

可以无损或者有损地对图片资源进行压缩,减小apk的大小。

五、线程优化

1、线程池的使用

a.避免反复地创建和销毁线程,提高线程的重复利用率。

b.通过Executors类创建线程池,来控制线程的数量和资源。

“`
//使用newFixedThreadPool来创建线程池

ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

//提交任务

threadPool.execute(new Runnable() {
@Override
public void run() {
//…
}
});
“`

2、AsyncTask的使用

通过AsyncTask来处理UI线程和后台线程的交互,避免在主线程中进行长时间的操作,从而导致ANR。

“`
public class DownloadTask extends AsyncTask{
@Override
protected String doInBackground(String… params) {
//这里进行耗时操作
return result;
}

@Override
protected void onProgressUpdate(Integer… values) {
super.onProgressUpdate(values);
//更新进度条
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//更新UI
}
}
“`

3、使用Handler和ThreadLocal减少内存占用

a.Handler

“`
private static class MyHandler extends Handler{

private final WeakReference mActivity;

public MyHandler(Activity activity){
mActivity =new WeakReference(activity);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(mActivity.get()!=null){
//执行UI操作或者其他操作
}
}
}

private MyHandler mHandler =new MyHandler(this);
“`

b.ThreadLocal

“`
private ThreadLocal threadLocal =new ThreadLocal(){
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
}
};

private class SimpleThread extends Thread{
@Override
public void run() {
SimpleDateFormat sdf =threadLocal.get();
//…
}
}
“`

六、APP启动优化

1、延迟加载

a.使用Fragment或者ViewPager可以延迟加载不必要的资源或者页面。

“`
public class MyFragment extends Fragment{
//…
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
//加载数据或者页面
}else{
//释放资源
}
}
}
“`

b.通过线程池进行延迟加载和预加载,提高App启动速度。

2、懒加载

延迟加载过后,还可以通过懒加载的方式加载不必要的资源,提高App的启动速度。

“`
public class LazyLoadFragment extends Fragment{

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView =inflater.inflate(R.layout.fragment_lazy,container,false);
return rootView;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(getUserVisibleHint()){
//加载数据或者页面
}
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);

if(isVisibleToUser&&isAdded()){
//加载数据或者页面
}
}
}
“`

七、总结

内存优化是Android开发中的一个重要环节,在开发过程中,多注意内存泄漏的问题,对Bitmap进行优化和管理,对布局和资源文件进行分类和压缩,选用合适的线程池和AsyncTask,延迟和懒加载,可以大大提高App的启动速度和运行效率。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/249551.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 17:13
下一篇 2024-12-12 17:13

相关推荐

  • Android ViewPager和ScrollView滑动冲突问题

    Android开发中,ViewPager和ScrollView是两个常用的控件。但是当它们同时使用时,可能会发生滑动冲突的问题。本文将从多个方面介绍解决Android ViewPa…

    编程 2025-04-28
  • Android如何点击其他区域收起软键盘

    在Android应用中,当输入框获取焦点弹出软键盘后,我们希望能够点击其他区域使软键盘消失,以提升用户体验。本篇文章将说明如何实现这一功能。 一、获取焦点并显示软键盘 在Andro…

    编程 2025-04-28
  • Android Studio HUD 实现指南

    本文将会以实例来详细阐述如何在 Android Studio 中使用 HUD 功能实现菊花等待指示器的效果。 一、引入依赖库 首先,我们需要在 build.gradle 文件中引入…

    编程 2025-04-27
  • Android和Vue3混合开发方案

    本文将介绍如何将Android和Vue3结合起来进行混合开发,以及其中的优势和注意事项。 一、环境搭建 在进行混合开发之前,需要搭建好相应的开发环境。首先需要安装 Android …

    编程 2025-04-27
  • Android Java Utils 可以如何提高你的开发效率

    Android Java Utils 是一款提供了一系列方便实用的工具类的 Java 库,可以帮助开发者更加高效地进行 Android 开发,提高开发效率。本文将从以下几个方面对 …

    编程 2025-04-27
  • Android JUnit测试完成程序自动退出决方法

    对于一些Android JUnit测试的开发人员来说,程序自动退出是一个经常面临的困扰。下面从多个方面给出解决方法。 一、检查测试代码 首先,我们应该仔细检查我们的测试代码,确保它…

    编程 2025-04-25
  • Android Activity启动流程

    一、Activity概述 Android应用程序是由许多Activity组成的。一个Activity代表一个屏幕上的窗口。用户与应用程序交互时,Activity会接收用户的输入并处…

    编程 2025-04-25
  • Android单元测试详解

    一、单元测试概述 单元测试是指对软件中的最小可测试单元进行检查和验证。在Android开发中,单元测试是非常重要的一环,可以保证代码的质量、稳定性以及可维护性。 在Android开…

    编程 2025-04-25
  • Android WebView加载本地HTML

    一、介绍 Android WebView是一个内置的浏览器,它允许开发人员在应用中嵌入网页。使用WebView可以轻松地在应用程序中显示本地或远程的HTML内容。本篇文章将重点讲述…

    编程 2025-04-24
  • Android Wakelock详解

    一、什么是Android Wakelock? 在Android应用开发中,Wakelock被广泛应用于保持屏幕或CPU处于唤醒状态,以便应用程序可以继续执行后台任务,直到任务完成。…

    编程 2025-04-24

发表回复

登录后才能评论