Android内存优化分析--贰

安卓内存数据分析和内存脚本分析教程分享 下面是详细课程目录:篇1.安卓内存入门篇(内存基础知识和命令) 0基础新篇-第1课 内存修改器介绍(试看)(新) 0基础新篇-第2课 内存数据类型和精确查找方法(高清试看)(新) 0基础新篇-第3课 数据类型内存范围和溢出分析(新) 0基础新篇-第4课 查找数据逆向思维(新) 0基础新篇-第5课 联合搜索和原理(新) 0基础新篇-第6课 浮点数之范围搜索(新) 0基础新篇-第7课 浮点联合搜索修改... 阅读详情

1 内存优化—减少内存使用(Reduce)

如果减少某些不必要内存的使用,也可以达到内存优化的目的。

比如说Bitmap。它在使用时会花掉较多的内存。那我们就可以考虑在应用bitmap时减少某些不必要内存的使用。

  • 边界压缩:一张拍出来的图片分辨率可能会很大,如果不做压缩去展示的话,会消耗大量内存,可能造成OOM,通过BitmapFactory.Options去设置inSampleSize,可以对图片进行边界的压缩,减少内存开销。(做法:先设置BitmapFactory.inJustDecodeBounds为true,然后decodeFile,这样将会只去解析图片大小等信息,避免了将原图加载进内存。拿到原图尺寸信息后,根据业务逻辑换算比例,设置inSampleSize,接着设置BitmapFactory.inJustDecodeBounds为false,最后再去decodeFile,从而实现对图片边界大小进行了压缩再展示。)

  • 色彩压缩:除此之外,还可以通过设置Bitmap图片的Config配置来减少内存使用。配置有以下四种:

    ALPHA_8(Alpha由8位组成,代表8位Alpha位图)

    ARGB_4444(由4个4位组成即16位,代表16位ARGB位图)

    ARGB_8888(由4个8位组成即32位,代表32位ARGB位图,图片质量最佳)

    RGB_565(R为5位,G为6位,B为5位,共16位,它是没有透明度的)

    如果配置不一样,需要的内存也不同。比如ARGB4444、ARGB8888、RGB565。配置的位数越高,图片质量越佳,当然需要的内存就越多。如果图片不需要透明度,就采用RGB565的配置。通过Bitmap.Config配置,也可以起到压缩图片大小作用。

    在实际中,可以通过以下代码来进行图片转bitmap解码时的Config。

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_menu_add, options);
  • 如果通过在列表中展示缩略图的形式来加载图片,如果需要查看高清图片,另启动一个页面(对话框)来加载高清图片,这样可以避免在列表中加载太多高清图片,减少内存开销。

2 内存优化—回收(Recycle)

一些资源时使用时记得回收,比如说BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap、TypeArray等资源的代码,应该在使用之后或者Activity销毁时及时关闭或者注销,否则这些资源可能将不会被回收,造成内存泄漏。

3 内存优化—重用(Reuse)

3.1 对象池

在程序里面经常会遇到的一个问题是短时间内创建大量的对象,导致内存紧张,从而触发GC导致性能问题。对于这个问题,我们可以使用对象池技术来解决它。通常对象池中的对象可能是bitmaps,views,messages等等。

比如说Message.obtain()方法。通过handler去发消息Message时,通过Message.obtain()来获得一个消息,就比直接通过new一个Message要更好。因为Message中内部就维护了一个对象池用来存放消息,通过obtain方法来取消息的话,会先从内部的对象池中去取,如果取不到,再去新创建一个消息进行使用。

再比如说线程池。开启新线程来执行任务可以用new Thread()来做,但这样做的弊端如下:

  • 每次new Thread新建对象性能差。

  • 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。

  • 缺乏更多功能,如定时执行、定期执行、线程中断。

相比new Thread,Java提供的四种线程池的好处在于:

  • 重用存在的线程,减少对象创建、消亡的开销,性能佳。

  • 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

  • 提供定时执行、定期执行、单线程、并发数控制等功能。

Java通过Executors提供四种线程池,分别为:

  • newSingleThreadExecutor 创建一个单线程化的Executor,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(比如FIFO)执行。最大特点是可以保证按照顺序执行各个任务,不会有多个线程是可活动的。

  • newScheduledThreadPool 创建一个定长线程池,可控制线程最大并发数,支持定时及周期性任务执行,类似于Timer。

  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  • newCachedThreadPool 创建一个可缓存的线程池。可创建的最大线程数量没有限制,如果长时间(60秒)没有向线程池中提交新任务,则空闲线程会被终止。

关于对象池的操作原理,请看下面的图示:

使用对象池技术有很多好处,它可以避免内存抖动,提升性能,但是在使用的时候有一些内容是需要特别注意的。通常情况下,初始化的对象池里面都是空白的,当使用某个对象的时候先去对象池查询是否存在,如果不存在则创建这个对象然后加入对象池。

但是我们也可以在程序刚启动的时候就事先为对象池填充一些即将要使用到的数据,这样可以在需要使用到这些对象的时候提供更快的首次加载速度,这种行为就叫做预分配。

使用对象池也有不好的一面,我们需要手动管理这些对象的分配与释放,所以我们需要慎重地使用这项技术,避免发生对象的内存泄漏。为了确保所有的对象能够正确被释放,我们需要保证加入对象池的对象和其他外部对象没有互相引用的关系。

3.2 缓存

无论是为了提高CPU的计算速度还是提高数据的访问速度,在绝大多数的场景下,我们都会使用到缓存。

例如缓存到内存里面的图片资源,网络请求返回数据的缓存等等。凡是可能需要反复读取的数据,都建议使用合适的缓存策略。比如图片三级缓存、ListView中的Adapter使用contentView进行复用、使用holder避免重复的findViewById。再比如以下的代码,都是缓存的体现。

        //原代码
        for (int i = 0; i < 1024; i++) {
            if(i<getCount()){
                Log.d("TAG", "some log" + i);
            }
        }
​
        //有缓存体现的代码,避免重复调用1024次getCount方法
        int count = getCount();
        for (int i = 0; i < 1024; i++) {
            if(i<count){
                Log.d("TAG", "some log" + i);
            }
        }
3.2.1 缓存中的lru算法

lru算法(Least Recently Use),即最近最少使用算法,在Android中比较常用。当内存超过限定大小时,凡是近时间内最少使用的那一个对象,就会从缓存容器中被移除掉。

LRU Cache的基础构建用法如下:

        //往缓存中添加图片,PicUrl是图片的地址,将其作为key,bitmap位图则作为value
        bitmapLRUCache.put(picUrl,bitmap);
        //通过picUrl图片地址,从缓存中取bitmap
        bitmapLRUCache.get(picUrl);

为了给LRU Cache设置一个比较合理的缓存大小值,我们通常是用下面的方法来做界定的:

        //当前应用最大可用内存
        long maxMemory = Runtime.getRuntime().maxMemory();
        //创建一个LRUCache,设置缓存大小界限为最大可用内存的八分之一
        BitmapLRUCache bitmapLRUCache = new BitmapLRUCache((int)maxMemory / 8);

使用LRU Cache时为了能够让Cache知道每个加入的Item的具体大小,我们需要Override下面的方法:

public class BitmapLRUCache extends LruCache<String,Bitmap> {
​
    public BitmapLRUCache(int maxSize) {
        super(maxSize);
    }
​
    @Override
    protected int sizeOf(String key, Bitmap value) {
        int byteCount = value.getByteCount();//该bitmap位图所占用的内存字节数
        return byteCount;
    }
}
3.2.2 避免创建大量的临时对象

如果创建大量的临时对象,会导致内存上出现抖动。

上图为Android Studio中Memory Monitor,图中的波浪线就表示,内存的开销忽上忽下,出现了抖动,此时应用容易出现卡屏掉帧。

为了避免创建大量临时对象,注意:

  • 在高频率执行的方法中注意尽量不要创建对象,像View的onTouch和onDraw方法

  • 在做较多的字符串拼接时,采用StringBuilder、StringBuffer。

4 内存优化—检查(Review)

代码写完了只是个开始。比较规范的编码,都需要Review的。代码检查时的注意点可参考上述内容。

接下来要提到的是UI检查。

4.1 查看UI布局是否过度绘制(overdraw)

查看的前提是:移动设备已经开启了开发者选项。

在开发者选项中,点击“调试GPU过度绘制”,将弹出对话框,然后选择“显示过度绘制区域”,如下图所示:

屏幕这时候会变得花花绿绿的. 这些颜色是用来帮助你诊断应用程序的显示行为的。

这些颜色用于表示每个像素被重绘的次数, 含义如下:

真实颜色: 没有被重绘

蓝色: 重绘一次

绿色: 重绘两次

粉色: 重绘三次

红色: 重绘四次或更多次

通过这个工具,可以实现这些事情:

  • 展示一个APP在何处做了不必要的渲染绘制。

  • 帮助你查看在哪里可以减少渲染绘制。

有些重绘是不可避免的. 尽量调整APP的用户界面, 目标是让大部分的屏幕都是真实的颜色以及重绘一次的蓝色。

PS:Activity是有默认颜色的,如果你已经在Layout文件中给页面设置了颜色,那么Activity的默认颜色可以去掉,这样也能减少一层绘制。

        setContentView(R.layout.activity_overdraw_01);
        //设置取消Activity的默认背景色
        getWindow().setBackgroundDrawable(null);

4.2 查看UI布局的渲染速度

查看的前提是:移动设备已经开启了开发者选项。

在开发者选项中,点击“GPU呈现模式分析”,将弹出对话框,然后选择“在屏幕上显示为条形图”,如下图所示:

这时,将会在屏幕下方出现条形图,如下图所示:

该工具会为每个可见的APP显示一个图表,水平轴即时间流逝, 垂直轴表示每帧经过的时间,单位是毫秒。

在与APP的交互中, 垂直栏会显示在屏幕上, 从左到右移动, 随着时间推移,绘制帧的性能将会迅速体现出来。

绿色的线是用于标记16毫秒的分隔线(PS:人眼的原因, 1秒24帧的动画才能感到顺畅. 所以每帧的时间大概有41ms多一点点(1000ms/24). 但是但是, 注意了, 这41ms不是全都留给你Java代码, 而是所有java native 屏幕等等的, 最后留给我们用java级别代码发挥的时间, 只有16~17ms),只要有一帧超过了绿线, 你的APP就会丢失一帧。

4.3 查看UI布局的层级和实现方式

有的UI界面写的效率比较低,我们可以通过一些工具来进行UI方面的视图检查。Hierarchy Viewer工具可以展示当前手机界面的View层级。

使用该工具的前提是:只能在模拟器或开发版手机上才能用,普通的商业手机是无法连上的。主要是出于安全考虑,普通商业手机中view server这个服务是没有开启的. Hierarchy Viewer就无法连接到机器获取view层级信息。(PS:如果愿意花功夫捣鼓,也可以在真机上强行开启View Server,详情见网上资料)

先打开模拟器运行要查看的页面,然后打开Hierarchy Viewer工具,它位于android的sdk所在目录中,具体位置为...\sdk\tools\hierarchyviewer.bat。打开后如图所示:

列表展示手机中已打开的页面(包括状态栏等)。这里以电话应用中的DialtactsActivity为例,双击DialtactsActivity,将会打开关于该页面的树状图。如下图所示:

图中标出了3个部分:

  • ① Tree View:

    树状图的形式展示该Activity中的View层级结构。可以放大缩小,每个节点代表一个View,点击可以弹出其属性的当前值,并且在LayoutView中会显示其在界面中相应位置。

  • ② Tree Overview

    它是Tree View的概览图。有一个选择框, 可以拖动选择查看。选中的部分会在Tree View中显示

  • ③ Layout View

    匹配手机屏幕的视图,如果在Tree View中点击了某个节点,呢么这个节点在手机中的真是位置将会在Layout View中以红框的形式被标出。

接下来介绍点击Tree View中某个节点时,它所展示的信息类似于下图:

下面的三个圆点,依次表示Measure、Layout、Draw,可以理解为对应View的onMeasure,onLayout,onDraw三个方法的执行速度。

  • 绿色:表示该View的此项性能比该View Tree中超过50%的View都要快。

  • 黄色:表示该View的此项性能比该View Tree中超过50%的View都要慢。

  • 红色:表示该View的此项性能是View Tree中最慢的。

如果界面中的Tree View中红点较多,那就需要注意了。一般的布局可能有以下几点:

  1. Measure红点,可能是布局中多次嵌套RelativeLayout,或是嵌套的LinearLayout都使用了weight属性。

  2. Layout红点,可能是布局层级太深。

  3. Draw红点,可能是自定义View的绘制有问题,复杂计算等。

5 UI布局优化

5.1 避免过度绘制(Overdraw)

5.2 减少布局层级

  • 尽量减少嵌套,去除不必要的父布局。

  • 尽量不要在RelativeLayout中嵌套使用RelativeLayout,相对布局它会有两次测量Measure两次layout。

  • LinearLayout使用Weight属性时,效率会降低至相对布局一样,出现多次测量Measure和布局Layout,所以尽量不要在LinearLayout嵌套LinearLayout时,两个都使用weight属性

  • 善用TextView、EditText等控件的Drawable属性来减少布局。

5.3 复用(id、style)

5.4 使用include、merge、viewStub标签

5.4.1 include标签

include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,这在布局编写上提供了大大的便利。

下面以在一个布局main.xml中用include引入另一个布局foot.xml为例。main.mxl代码如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <ListView
        android:id="@+id/simple_list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="@dimen/dp_80" />
    <include layout="@layout/foot.xml" />
</RelativeLayout>

 其中include引入的foot.xml为公用的页面底部,foot.xml代码如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_above="@+id/text"/>
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_alignParentBottom="true"
        android:text="@string/app_name" />
</RelativeLayout>

<include>标签唯一需要的属性是layout属性,指定需要包含的布局文件。在该标签中,还可以定义android:id和android:layout_*属性来覆盖被引入布局根节点的对应属性值。注意重新定义android:id后,子布局的顶结点i就变化了。

5.4.2 merge标签

在使用了include后可能导致布局嵌套过多,多余不必要的layout节点,从而导致解析变慢,不必要的节点和嵌套可通过上文中提到的hierarchy viewer来查看。而merge标签可以消除那些include时不必要的layout节点。

merge标签可用于两种典型情况:

  1. 布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容试图的parent view就是个FrameLayout,所以可以用merge消除只剩一个。

  2. 某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中

以上一节中的<include>标签的示例为例,用hierarchy viewer查看main.xml布局如下图:

可以发现多了一层没必要的RelativeLayout,将foot.xml中RelativeLayout改为merge,如下:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_above="@+id/text"/>
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_alignParentBottom="true"
        android:text="@string/app_name" />
</merge>

运行后再次用hierarchy viewer查看main.xml布局如下图:

这样就不会有多余的RelativeLayout节点了。

5.4.3 viewStub标签

viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。

viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。

下面以在一个布局main.xml中加入网络错误时的提示页面network_error.xml为例。main.mxl代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    ……
    <ViewStub
        android:id="@+id/network_error_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout="@layout/network_error" />
</RelativeLayout>

其中network_error.xml为只有在网络错误时才需要显示的布局,默认不会被解析,示例代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/network_setting"
        android:layout_width="@dimen/dp_160"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="@string/network_setting" />
    <Button
        android:id="@+id/network_refresh"
        android:layout_width="@dimen/dp_160"
        android:layout_height="wrap_content"
        android:layout_below="@+id/network_setting"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="@dimen/dp_10"
        android:text="@string/network_refresh" />
</RelativeLayout>

在java中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下

private View networkErrorView;
private void showNetError() {
    // not repeated infalte
    if (networkErrorView != null) {
        networkErrorView.setVisibility(View.VISIBLE);
        return;
    }
    ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
    networkErrorView = stub.inflate();
    Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);
    Button refresh = (Button)findViewById(R.id.network_refresh);
}
private void showNormal() {
    if (networkErrorView != null) {
        networkErrorView.setVisibility(View.GONE);
    }
}

 在上面showNetError()中展开了ViewStub,同时我们对networkErrorView进行了保存,这样下次不用继续inflate。

上面展开ViewStub部分代码

ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
networkErrorView = stub.inflate();

也可以写成下面的形式

View viewStub = findViewById(R.id.network_error_layout);
viewStub.setVisibility(View.VISIBLE);   // ViewStub被展开后的布局所替换
networkErrorView =  findViewById(R.id.network_error_layout); // 获取展开后的布局

两者效果一致,只是不用显示的转换为ViewStub。通过viewstub的原理我们可以知道将一个view设置为GONE不会被解析,从而提高layout解析速度,而VISIBLE和INVISIBLE这两个可见性属性会被正常解析。

5.5 使用Spannable或Html.fromHtml

举例说明,比如下图中红框标出来的效果:

比较笨的方法就是使用多个TextView,然后设置不同的字体及颜色。

其实用一个TextVIew就可以实现,类似如下代码

 String text = String.format("¥%1$s  门市价:¥%2$s", 18.6, 22);
 int z = text.lastIndexOf("门");
 SpannableStringBuilder style = new SpannableStringBuilder(text);
 style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //设置第一个符号的字号
 style.setSpan(new ForegroundColorSpan(Color.parseColor("#afafaf")), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //设置门市价那段文本的字体的颜色
 style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //设置门市价那段文本的字体的字号
​
 tv.setText(style);


Android内存优化(五)详解内存分析工具MAT 在这个系列的前四篇文章中,我分别介绍了DVM、ART、内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT。 阅读详情

相关推荐

安卓内存基础教程

声明:下面的教程是本人用于安卓内存数据技术分析和逆向安全研究,禁止非法用途。同意声明才往下看。 本教程是我利用业余时间出的。应该是早期极为罕见的第一套完整体系的安卓网游内存分析的教程。教程简单、粗暴、直接有效,实用性很强的。现在公开给大家,希望对各位手机安全程序员的朋友有一定帮助。后面的帖子我也会跟大家讲价下安卓内存定位、安卓内存基地址+偏移+偏移、安卓内存管理等原理。 链接: https://p...

zibenyuan的博客 3524

内存优化02

内存优化021 内存优化—减少内存使用(Reduce)如果减少某些不必要内存的使用,也可以达到内存优化的目的。比如说Bitmap。它在使用时会花掉较多的内存。那我们就可以考虑在应用bitmap时减少某些不必要内存的使用。 边界压缩:一张拍出来的图片分辨率可能会很大,如果不做压缩去展示的话,会消耗大量内存,可能造成OOM,通过BitmapFactory.Options去设置inSampleSize,可

github_39295111的博客 382

实践App内存优化:如何有序地做内存分析与优化

由于项目里之前线上版本出现过一定比例的OOM,虽然比例并不大,但是还是暴露了一定的问题,所以打算对我们App分为几个步骤进行内存分析和优化,当然内存的优化是个长期的过程,不是一两个版本的事,每个版本都需要收集线上内存数据进行监控以及分析。 版本迭代过程中,内存增长过快,不仅会导致一定概率的OOM,运行时若出现内存抖动,导致频繁GC,则会对App的流畅度以及用户体验造成很大影响。 本文主...

南朝烟雨的博客 1243

PIC代码优化笔记(降低.bin文件尺寸)

一次代码优化实战

含光左卫的工作笔记集 486

C#:WPF格式转Winform格式

WPF格式转Winform格式

Hello C++ 1295

基于FPGA的DDR学习——1.基础知识

⚪DDR2(Double Data Rate2)SDRAM是由JEDEC(电子设备工程联合委员会)开发的第三代SDRAM内存技术标准,1.8V工作电压,240线接口,提供了相较于DDR SDRAM更高的运行效能与更低的电压,同样采用在时钟的上升/下降沿同时进行数据传输的基本方式,但拥有两倍于上一代DDR内存预读取能力(即4bit数据预取能力),其常见的频率规范有DDR2 400\533\667\800\1066\1333等,总线频率553MHZ的DDR2内存只需133MHZ的工作频率。

qq_44932488的博客 2070

位置无关(PIC)代码原理剖析

共享库的一个关键目的是为了使多个进程能够共享内存中的同一份代码拷贝,已达到节约内存资源的目的。如何做到呢?一种方法是预先为每一个共享库指定好加载的地址范围,然后要求加载器总是将共享库加载至指定的位置。这种方法尽管很简单,但是会产生一些严重的问题。因为就算一个进程并没有用到某个库,相应的地址范围依然会被保留下来,这是一种效率很低的内存使用方式。另外,这种方法管理起来也很困难。我们必须保证预留的地址块

PacMan的专栏 1万+

Web端百度离线地图3.0实战:从零搭建到私有化部署

本文详细介绍了Web端百度离线地图3.0的完整实战流程,从核心SDK本地化、功能模块下载到地图瓦片部署。通过逐步修改代码与配置,实现在无外网环境下的私有化部署,解决了内网或网络不稳定场景下的地图应用需求,并提供了关键的避坑指南。

n7o8p的博客 714

深入探索 Android 内存优化(炼狱级别)

前言 成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~。 本篇是 Android 内存优化的进阶篇,难度可以说达到了炼狱级别,建议对内存优化不是非常熟悉的仔细看看前篇文章:Android性能优化之内存优化,其中详细分析了以下几大模块: 1)、Android的内存管理机制 2)、优化内存的意义 3)、避免内存泄漏 4)、优化内存空间 5)、图片管理模块的设计与实现 如果你对以上基础内容都比较了解了,那么我们便开始 Android 内...

idaretobe的专栏 4148

避坑指南:HslCommunication连接西门子PLC时常见的5个错误及解决方法(S7-1200/S1500适用)

本文详细解析了使用HslCommunication连接西门子S7-1200/S1500 PLC时常见的5个错误及解决方法,包括基础连接配置、数据块读写异常、连接闪断、防火墙与权限问题以及高级调试技巧。通过实战案例和代码示例,帮助开发者快速定位和解决连接问题,提升工业自动化项目的开发效率。

weixin_30752699的博客 397

Fiddler抓包实战:5分钟搞定微信公众号历史消息接口分析(附完整Python代码)

本文详细介绍了如何使用Fiddler抓包工具逆向分析微信公众号历史消息接口,并提供完整的Python代码实现。从环境准备、动态参数捕获到商业级采集系统架构设计,全面解析了突破官方接口限制的技术方案,帮助开发者高效获取公众号文章数据。

tree8的博客 329

Android应用开发性能优化完全分析

1 背景其实有点不想写这篇文章的,但是又想写,有些矛盾。不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结、我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只给出啥啥啥不能用,啥啥啥该咋用等,却很少有较为系统的进行真正性能案例分析的,大多数都是嘴上喊喊或者死记住规则而已(当然了,这话我自己听着都有些刺耳,实在不好意思,其实关于性能优化的优质博文网上也还是有很多

工匠若水 10万+

YOLOv11在RK3588芯片上的NPU加速与INT8量化部署全面指南

RK3588 NPU适配YOLOv11的关键技术要点 摘要:本文详细分析了Rockchip RK3588 NPU的硬件架构特性及其对YOLOv11模型的适配优化方案。RK3588 NPU采用三核设计,具备6TOPS算力,包含192个MAC单元和128KB专用SRAM。YOLOv11作为最新目标检测模型,其CSPNet-v5骨干网络、PANet特征金字塔和SiLU激活函数需要特殊适配处理。文章系统介绍了从PyTorch模型导出、ONNX优化到RKNN模型转换的完整流程,重点阐述了NPU不支持的算子处理方案和量

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1358

安卓内存优化

文章目录为什么要进行内存优化优化步骤1,查看当前的应用内存使用情况,发现是否有内存泄漏2,内存泄漏点查找,并解决问题3,其它一些日常项目中编码的注意点 为什么要进行内存优化 安卓应用如果不进行内存优化,一些不良的代码习惯或编码可能有内存泄漏,甚至导致OOM。这样的应用随着长时间的使用,经常会出现越来越卡的现象,严重的甚至会直接闪退,进而给用户带来劣质感,严重影响用户体验和使用,最终导致用户流失。 对于你的手机,都有自己的app内存配置参数,可以adb查看 adb shell getprop | findst

weixin_41605683的博客 2634

Microsemi Libero系列教程(六)——Identify片上逻辑分析仪的使用

文章目录FPGA如何进行在线调试关于Microsemi片上逻辑分析仪FPGA片上逻辑分析仪原理预期效果0.准备一个创建好的Libero工程1.新建identify工程,并添加想要监测的信号2.管脚分配,编译下载3.设置触发类型4.IICE逻辑分析仪核资源占用 系列教程:Microsemi Libero系列教程 FPGA如何进行在线调试 对于嵌入式系统来说,如单片机,进行硬件级程序调试时,通常采用的是JLink/ST-Link调试器,在线调试的方式来获取程序实时运行的状态,可以观察程序运行流程、各种变量的值

whik1194的博客 1万+

第八节:Orin NX 修改pinmux

读SPI1对应的寄存器,看对应的GPIO口是否被复用为SPI功能。说明GPIO口的功能已经被复用为SPI。烧录或者命令行烧录,都是根据。这里我们把文件统一命名成。文件,Orin NX的。测试SPI功能,基于。

孤独旅客的博客 792

安卓手机内存优化调研

背景 现在安卓手机在相机操作下,不可避免要大量消耗内存资源,同时当今手机如同电脑一样,前台相机,后台各种app进程,都会消耗内存。因而会出现相机场景下,系统可用内存不足,内存压力增加不少,对相机性能会带来严重的影响。因此需要调查相机场景下的内存优化方法。 memcg调研 memcg的好处: 1 监控进程使用内存 站在一个普通Linux开发者的角度,如果能控制一个或者一组进程所能使用的内存数,那么就算代码有bug,内存泄漏也不会对系统造成影响,因为可以设置内存使用量的上限,当到达这个值之后可..

buhui912的专栏 2972

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

安卓入门六十 内存优化

与以前的 Android Monitor 工具中的内存计数相比,新的内存分析器以不同的方式记录您的内存,因此,您的内存使用量现在看上去可能会更高些。但是,如果您的应用分配内存的速度比系统回收内存的速度快,当回收器要释放足够的内存以满足您的分配需要时,您的应用可能会产生延迟。但是,Android 8.0 及更高版本附带一个设备内置性能剖析工具,该工具可跟踪所有分配,因此,在 Android 8.0 及更高版本上,此数字始终表示您的应用中待处理的 Java 对象总数。当您退出分析会话时,会丢失堆转储。

weixin_52735932的博客 899

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Android 性能优化--内存优化分析总结

强大的Java Heap分析工具,查找内存泄漏及内存占用生成整体报告、分析问题等线下深入使用官网下载地址:www.eclipse.org/mat/downloa… ,这个地址是不是有你熟悉的单词,嗯,没错啦,MAT是Eclipse中的一个插件,因为现在开发过程中很多人都使用了IDEA或者Android Studio,所以你不想下载Eclipse的话呢,你可以去下载MAT的独立版,解压之后里面有一个MemoryAnalyzer.exe的可执行文件,直接点击就可以使用了。

缘来的精彩的博客 2221

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Android 内存分析

内存性能分析器是 Android Profiler 中的一个组件,可帮助识别可能会导致应用卡顿、冻结甚至崩溃的内存泄漏和内存抖动。它显示一个应用内存使用量的实时图表,可以捕获堆转储、强制执行垃圾回收以及跟踪内存分配。或者,可以从命令行使用 dumpsys检查应用内存,还可以在 logcat 中查看 GC 事件。

weixin_75102992的博客 2242

Android如何分析内存并优化

通过使用 Android Profiler、Memory Profiler 和 LeakCanary 等工具,开发者可以有效地分析和检测应用中的内存问题。结合适当的优化技巧,如避免内存泄漏、使用合适的数据结构、优化图片加载和布局等,可以显著提升应用的性能和稳定性。内存优化是一个持续的过程,定期进行内存分析和优化有助于确保应用始终高效运行。

彬_小彬的博客 1694

Android性能优化系列:内存优化

实践App内存优化:如何有序地做内存分析与优化

Vincent的博客 7495

【安卓笔记】OOM与内存优化

简单介绍:1. OOM常见场景和解决方案。2. 内存分析命令的功能和使用。3. 内存分析工具MAT的功能和简单使用方法。

liosen的博客 1492

Android性能优化之内存分析

内存抖动就是不停的在新生代创建对象,创建对象很多,会有空间分配担保,新生代空间比较小占1/3,老年代2/3,当新生代空间不够时,老年代会腾挪一部分空间给新生代,导致老年代空间下降,这个时候假设创建了大对象,从新生代经过了from到to,年龄足够到了老年代,这个时候空间不够,如果没有连续的空间,就会导致OOM。GC过程中会暂停用户线程包括UI线程,Stop the World,频繁的创建,释放对象,GC频繁出现,就会导致App整体卡顿。引用计数法:一个对象身上没有引用,不可用,这个对象就会被回收。

ChenYiRan123456的博客 979

android内存脚本教程,安卓内存

按键安卓内存逆向教程意欲盗版翻录注意(部分基础入门试看视频免费公布给大家学习):进阶高级实战视频现在要求个人微信认证,视频会自动检测,翻录的学员直接公布个人视频、个人资料加上不诚信和骗子专用章在百度和我的网站。请翻录狗非诚勿扰。声明:本教程只做技术游戏,里面数据分析只用来技术研究,禁止非法用途,后果自负。安卓内存脚本不同于PC端,做脚本的思维方式很多都是不同的,不要把PC端的思维强加进去。一般我们...

weixin_36278817的博客 3925

android性能优化之 内存优化

避免在onDraw方法里面执行对象的创建,onDraw界面,图像,view有变动,则会重新执行onDraw,如果在里面进行对象创建,则会影响绘制时间,如果onDraw绘制时间较长,则会引起UI卡顿,且onDraw频繁执行,创建也会频繁执行。- 问题分析: ‌是指应用程序在运行过程中,申请的内存超过了系统或虚拟机可分配的内存上限,导致程序崩溃的现象、尤其是在处理大内存对象(如位图)或内存泄漏时。- 自带内存监控工具?- 内存抖动:突然间申请很多变量和空间后再释放,且GC时所有进程会暂停,重复此行为。

lui0617的博客 2104
上一篇: Android内存优化分析
下一篇: Android系统设计中存在设计模式分析
yipeng95
博客等级 码龄9年 0粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值