Android 内存优化知识点梳理总结

Android 内存优化知识点梳理总结

一、内存泄漏

内存泄漏指由于疏于释放内存而导致内存溢出的一种情况。在 Android 中,可能导致内存泄漏的场景包括:

  • 非静态内部类引用外部类实例
  • Handler 引起的内存泄漏
  • 单例模式中的 Context 引起的内存泄漏
  • ListView/RecyclerView 的 ViewHolder 引起的内存泄漏
  • Bitmap 引起的内存泄漏

解决方案包括:

  • 尽量避免使用非静态内部类引用外部类实例,如果必须使用可以使用弱引用或静态内部类
  • 尽量使用 Application Context 而不是 Activity Context
  • 在使用 Handler 时,尽量使用静态内部类并在内部弱引用一下外部类
  • 在 Activity/Fragment 销毁时及时取消掉相关联的消息
  • 在使用 ListView/RecyclerView 时,尽量减少 ViewHolder 中的变量数目以及对 Bitmap 等占用较大的资源的引用

以 Handler 引起的内存泄漏的示例说明:

public class MyActivity extends Activity {

    private HandlerThread mWorkThread;
    private Handler mWorkHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWorkThread = new HandlerThread("MyWorkThread");
        mWorkThread.start();
        mWorkHandler = new Handler(mWorkThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                // do something
            }
        };
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 导致内存泄漏的写法,需要手动调用 quit 方法停止 HandlerThread
        mWorkThread.quit();
    }

}

在上述代码中,由于 HandlerThread 是用在 Handler 中的,而 Handler 又被赋值给了成员变量 mWorkHandler,因此在 Activity onDestroy 时必须调用 mWorkThread.quit() 来手动停止 HandlerThread,否则就会导致内存泄漏。

二、内存抖动

内存抖动指的是申请一次性大量内存,而同时又频繁地进行内存分配和回收导致 GC 频繁执行的一种情况。

Android 中可能导致内存抖动的场景包括:

  • 频繁地创建临时对象
  • 频繁地使用 String 进行字符串拼接

解决方案包括:

  • 尽量避免频繁地创建临时对象,可以使用对象池或者使用静态方法/属性等方式来代替创建对象
  • 尽量避免频繁地使用 String 进行字符串拼接,可以使用 StringBuilder 或者使用其他方式来代替字符串拼接

以频繁地使用 String 进行字符串拼接的示例说明:

public class MyActivity extends Activity {

    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.textview);
    }

    public void onButtonClick(View view) {
        String result = "";
        for (int i = 0; i < 100000; i++) {
            result += i;
        }
        mTextView.setText(result);
    }

}

在上述代码中,当按钮点击时会频繁地进行字符串拼接,由于 String 拼接会产生大量的临时对象,导致了内存抖动。改进的方案应该是使用 StringBuilder 进行字符串拼接,例如:

public class MyActivity extends Activity {

    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.textview);
    }

    public void onButtonClick(View view) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 100000; i++) {
            builder.append(i);
        }
        mTextView.setText(builder.toString());
    }

}

三、大图加载

在 Android 中,由于内存有限制,一些较大的图片如果直接加载会导致 OOM 错误的出现,因此需要进行图片压缩或者分块加载等处理。

解决方案包括:

  • 使用图片压缩或者缩放等方式减少图片内存占用
  • 对于较大的图片,可以使用分块加载的方式进行处理,例如使用 SubsamplingScaleImageView 等库

以图片压缩的示例说明:

public class MyActivity extends Activity {

    private ImageView mImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImageView = findViewById(R.id.imageview);
        // 加载大图
        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/test.jpg");
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        // 计算出压缩比例
        int scaleFactor = Math.min(width/1000, height/1000);
        if (scaleFactor <= 0) {
            scaleFactor = 1;
        }
        // 根据压缩比例缩小图片
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = scaleFactor;
        Bitmap compressedBitmap = BitmapFactory.decodeFile("/sdcard/test.jpg", options);
        mImageView.setImageBitmap(compressedBitmap);
    }

}

在上述代码中,首先加载原始的大图,然后根据图片实际大小计算出需要压缩的比例,最后通过 BitmapFactory.Options 进行图片压缩,从而减少了图片的内存占用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android 内存优化知识点梳理总结 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • webapi接口测试工具:swagger

    Web API接口测试工具:Swagger Web API是现代Web应用程序的核心,它提供了一种标准化的方法来与远程应用程序进行通信。Web API接口的开发和测试是一个繁琐而重要的任务。在测试API接口时,为了确保能够完全测试每个API的不同功能,您需要一种实用的工具,Swagger是一个很好的选择。 Swagger是一个流行的Web API开发框架,它…

    其他 2023年3月28日
    00
  • 如何安装windows7旗舰版

    如何安装Windows 7旗舰版 Windows 7旗舰版是一款流行的Windows操作系统版本,本文将介绍如何安装Windows 7旗舰版。在进行本操作前,请确保你拥有Windows 7旗舰版的安装光盘或下载好的镜像文件。 步骤一:备份数据 在进行Windows 7旗舰版的安装之前,我们建议你先备份重要数据。因为安装Windows将格式化系统磁盘,导致其中…

    其他 2023年3月28日
    00
  • CAD怎么建立三维模型? CAD几种建模思路分析

    CAD建立三维模型的详细攻略 CAD(计算机辅助设计)是一种广泛应用于工程设计和制造领域的技术,它可以帮助工程师和设计师创建精确的三维模型。下面是CAD建立三维模型的详细攻略,包括两个示例说明。 1. 攻略一:基于实体建模的思路 基于实体建模是CAD中最常用的建模思路之一,它通过创建实体对象并对其进行操作来构建三维模型。以下是基于实体建模的步骤: 步骤一:创…

    other 2023年7月28日
    00
  • Spring如何使用xml创建bean对象

    Spring如何使用XML创建Bean对象 以下是使用XML配置文件创建Bean对象的完整攻略: 创建XML配置文件:在Spring项目中创建一个XML配置文件(例如applicationContext.xml)。 声明命名空间:在XML文件的根元素中声明Spring的命名空间,以便使用Spring的XML配置。 示例代码: xml <beans xm…

    other 2023年10月15日
    00
  • android上superuser获取root权限原理解析

    Android上Superuser获取Root权限原理解析 什么是Superuser? 在Android系统中,有些应用程序需要获取Root权限才能够执行一些敏感操作,比如修改系统设置、进入系统目录等等。Superuser就是一种允许应用程序获取Root权限的工具。 当安装Superuser后,用户可以决定哪些应用程序可以访问Root权限,哪些应用程序被禁止…

    其他 2023年3月28日
    00
  • Win10下ftp搭建配置图文教程(测试成功)

    Win10下ftp搭建配置图文教程 FTP(File Transfer Protocol,文件传输协议)是一个在计算机之间进行文件传输的标准协议。在Win10中,我们可以搭建自己的FTP服务器来传输文件。本文将为大家详细介绍Win10下ftp搭建配置的过程。 1. 安装IIS 首先,我们需要安装IIS(Internet Information Service…

    other 2023年6月27日
    00
  • php遍历树的常用方法汇总

    非常感谢您对“php遍历树的常用方法汇总”的关注。在这篇文章中,我们将会讲解php遍历树的几种常用方法,并提供一些示例,方便大家更好地理解。主要内容如下: 一、深度优先遍历DFS 深度优先遍历是遍历树的一种经典方法。对于一棵树而言,深度优先遍历一般是通过递归实现的。具体来说,我们可以先遍历当前节点的左子树,再遍历右子树,最后才访问当前节点。以下是一个使用深度…

    other 2023年6月27日
    00
  • 合金装备5幻痛没有声音怎么办_没有声音的快速解决方法

    合金装备5幻痛没有声音怎么办? 如果您在玩合金装备5幻痛时遇到了没有声音的情况,不用担心,下面是几种常见的解决方法。 解决方案1:检查游戏设置 第一步,您需要检查游戏设置,确保您没有将音量设置为“0”。在游戏中按下ESC键打开菜单,然后选择“选项”和“音频”,然后将所有音量滑块调整到您喜欢的位置。 如果您仍然无法听到游戏中的声音,请继续尝试下一个解决方案。 …

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部