Android手机系统优化方法

Android手机系统优化方法,第1张

1. 手机一键优化 :包含内存占用、手机存储、系统内存优化、垃圾文件清理四个选择,点击“一键优化”即可。不仅可以显著的提高手机运行速度,还可以节省存储卡空间、降低手机CPU使用率,不再纠结于智能手机的卡吧-死机- -!

使用窍门:手机开机一段时间后或者玩大型游戏前点一下,最简单最快速提升系统性能和速度。

2. 清理网络缓存 :网络程序占用的缓存管理,可以节省手机内存空间和提高上网速度。很常遇到的'一个现象,APK安装包体积很少,但运行一段时间后缺累积了上M的缓存,导致整体在手机内存空间占用率高,内存空间越少,系统所能装的软件就会越少了,经常性的清理网络缓存能使您的手机能装更多的软件。

单个 *** 作:点击程序图标进入,点击“清除缓存”即可清理该程序缓存,点击手机“返回”按键,即可返回系统优化界面。

批量 *** 作:点击“清理网络缓存”按钮进入,点击“清除缓存”即可清理当前程序缓存,点击手机“返回”按键,即可进入下一个程序 *** 作界面,所有程序清理完成后,点击手机“返回”按键,返回系统优化界面。

3. 默认程序管理 :管理手机系统默认的执行程序,比如上网默认打开的浏览器(ucweb,QQ浏览器等)、音乐默认播放程序(酷狗,天天动听)等。目前暂时只支持单个设置。

单个 *** 作:点击程序图标进入,点击“清除默认设置”即可,点击手机“返回”按键,即可返回系统优化界面。

批量 *** 作:点击“重置以上默认打开程序”进入,点击“清除默认设置”即可清除当前程序设置,点击手机“返回”按键,即可进入下一个程序 *** 作界面,所有程序清理完成后,点击手机“返回”按键,返回系统优化界面。

4. 手机节电优化 :可以进行节电优化和查看电视状态、使用详情。

点击“节点优化(21项)”进入,可以看到21条android手机节点秘籍,根据文字 *** 作即可,让你的手机拥有超长的待机时间。

内存优化就是对内存问题的一个预防和解决,做内存优化能让应用挂得少、活得好和活得久。

挂的少:

“挂”指的是 Crash,内存问题导致 Crash 的具体表现就是内存溢出异常 OOM。

活得好:

活得好指的是使用流畅,Android 中造成界面卡顿的原因有很多种,其中一种就是由内存问题引起的。内存问题之所以会影响到界面流畅度,是因为垃圾回收(GC,Garbage Collection),在 GC 时,所有线程都要停止,包括主线程,当 GC 和绘制界面的 *** 作同时触发时,绘制的执行就会被搁置,导致掉帧,也就是界面卡顿。

活得久:

活得久指的是我们的应用在后台运行时不会被干掉。Android 会按照特定的机制清理进程,清理进程时优先会考虑清理后台进程。清理进程的机制就是LowMemoryKiller。在 Android 中不同的进程有着不同的优先级,当两个进程的优先级相同时,低杀会优先考虑干掉消耗内存更多的进程。也就是如果我们应用占用的内存比其他应用少,并且处于后台时,我们的应用能在后台活下来,这也是内存优化为我们应用带来竞争力的一个直接体现。

内存占用是否越少越好?

当系统 内存充足 的时候,我们可以多用 一些获得更好的性能。当系统 内存不足 的时候,我们希望可以做到 ”用时分配,及时释放“。内存优化并不能一刀切。

我们都知道,应用程序的内存分配和垃圾回收都是由Android虚拟机完成的,在Android 5.0以下,使用的是Dalvik虚拟机,5.0及以上,则使用的是ART虚拟机。

Android虚拟机Dalvik和ART

1、内存区域划分

详细请看以下两篇文章(建议全看):

java内存四大区_JVM内存区域划分

Android 内存机制

2、内存回收

垃圾收集的标记算法(找到垃圾):

垃圾收集算法(回收垃圾):

引用类型:强引用、软引用、弱引用、虚引用

对象的有效性=可达性+引用类型

JAVA垃圾回收机制-史上最容易理解看这一篇就够了

Android:玩转垃圾回收机制与分代回收策略

android中还存在低杀机制,这种情况属于系统整机内存不足,直接把应用进程杀掉的情况。

Android后台杀死系列:LowMemoryKiller原理

1、内存溢出

系统会给每个App分配内存空间也就是heap size值,当app占用的内存加上申请的内存超过这个系统分配的内存限额,最终导致OOM(OutOfMemory)使程序崩溃。

通过命令 getprop |grep dalvik.vm.heapsize 可以获取系统允许的最大

注意:在设置了heapgrowthlimit的状况下,单个进程可用最大内存为heapgrowthlimit值。在android开发中,若是要使用大堆,须要在manifest中指定android:largeHeap为true,这样dvm heap最大可达heapsize。

关于heapsize &heapgrowthlimit

2、内存泄漏

Android系统虚拟机的垃圾回收是通过虚拟机GC机制来实现的。GC会选择一些还存活的对象作为内存遍历的根节点GC Roots,通过对GC Roots的可达性来判断是否需要回收。内存泄漏就是 在当前应用周期内不再使用的对象被GC Roots引用,造成该对象无法被系统回收,以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费,使实际可使用内存变小。简言之,就是 对象被持有导致无法释放或不能按照对象正常的生命周期进行释放。

Android常见内存泄漏汇总

3、内存抖动

指的是在短时间内大量的新对象被实例化,运行时可能无法承载这样的内存分配,在这种情况下就会导致垃圾回收事件被大量调用,影响到应用程序的UI和整体性能,最终可能导致卡顿和OOM。

常见情况:在一些被频繁调用的方法内不断地创建对象。例如在View 的onDraw方法内new 一些新的对象。

注意内存抖动也会导致 OOM,主要原因有如下两点:

1、Android Studio Profiler

作用

优点

内存抖动问题处理实战

理解内存抖动的概念的话,我们就能明白只要能找到抖动过程中所产生的对象及其调用栈,我们就能解决问题,刚好Android Studio 的Porfiler里面的Memory工具就能帮我们记录下我们 *** 作过程中或静止界面所产生的新对象,并且能清晰看到这些对象的调用栈。

选择Profile 中 的Memory ,选择 Record Java/Kotlin allocations,再点击Record开始记录, Record Java/Kotlin allocations 选项会记录下新增的对象。

*** 作完成之后,点击如图所示的红脑按钮,停止记录。

停止记录后,我们就可以排序(点击 Allocations可以排序)看看哪些对象或基本类型在短时间被频繁创建多个,点击这些新增的对象就可以看到它的完成的调用链了,进而就找找到导致内存抖动的地方在哪里了。

2、利用DDMS 和 MAT(Memory Analyzer tool)来分析内存泄漏

我们利用工具进行内存泄漏分析主要是用对比法:

a.先打开正常界面,不做任何 *** 作,先抓取一开始的堆文件。

b.一顿胡乱 *** 作,回到原来 *** 作前的界面。主动触发一两次GC,过10秒再抓取第二次堆文件。

c.通过工具对比,获取胡乱 *** 作后新增的对象,然后分析这些新增的对象。

DDMS作用:抓取堆文件,主动触发GC。(其实也是可以用Android Studio 的Profile里面的Memory工具来抓取堆文件的,但是我这边在利用Profile 主动触发gc 的时候会导致程序奔溃,也不知道是不是手机的问题,所以没用Android Studio的Profiler)

MAT作用:对堆文件进行对比,找到多出的对象,找到对象的强引用调用链。

以下是详细的过程:

步骤1.打开DDMS,选择需要调试的应用,打开初始界面,点击下图的图标(Dump Hprof File)先获取一次堆文件。

步骤2.对应用随便 *** 作后,回到一开始的界面,先多触发几次GC ,点击下图的图标(Cause Gc)来主动触发GC,然后再次点击 Dump Hprof File 图标来获取堆文件。

步骤3.通过Android Studio Profile 或者 DDMS dump 的堆文件无法在MAT 打开,需要借助android sdk包下的一个工具hprof-conv.exe来转换。

格式为 hprof-conv 旧文件路径名 要转换的名称;

例如:hprof-conv 2022-04-13_17-54-40_827.hprof change.hprof

步骤4.把两份堆文件导入MAT,然后选择其中第二次获取的堆文件,点击 如图所示的 Histogram查看。

步骤5.点击下图图标,Compare To Another Heap Dump ,选择另一份堆文件。

6.会得出下图所示的 Hitogram 展示,我们主要看Objects 这一列。 如下图所示 “+ 2” 则代表前面两份堆文件对比,这个对象多了两个,我们主要就是要分析这些多了出来,没有被回收的对象。

7.加入我们从增加的对象中,看到了MainActivity ,则需要从一开始打开的Hitogram 展示里面找到这个对象的调用栈。如下图所示,搜索MainActivity

8.看到下图所示解雇,然后鼠标右键点击下图红色圈圈着的MainActivity ,选择 Merger Shortest Paths to Gc Roots ,再选择 exclude all phantom/weak/soft etc.references ,就可以看到这个MainActivity 对象的强引用链,至此我们就可以找到MainActivity对象是被什么引用导致无法回收了。

3、内存泄露检测神器之LeakCanary(线下集成)

自行学习了解,接入简单,使用简单,基本可以解决大部分内存泄漏问题。

github地址 : https://github.com/square/leakcanary/

学习地址 : https://square.github.io/leakcanary/changelog/#version-22-2020-02-05

针对内存抖动的建议:

针对内存泄漏问题的建议:

针对内存溢出问题的建议(主要就是要减少内存占用):

建议参考:

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

对于 优化的大方向,我们应该优先去做见效快的地方,主要有以下三部分:内存泄漏、内存抖动、Bitmap。完善监控机制也是我们的重点,能帮助我们对内存问题快速分析和处理。

参考:

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

文章、布局优化神器 include 、merge、ViewStub 标签详解

Tips:

include 标签使用:

//include_test.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center_horizontal"

android:orientation="vertical">

<TextView

android:id="@+id/textView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="20dp"

android:text="@string/textview"

android:textSize="24sp"/>

<EditText

android:id="@+id/editText"

android:hint="@string/divide"

android:layout_width="300dp"

android:layout_height="wrap_content"/>

</LinearLayout>---------------------------------------------------------------

//include_text_relative

<?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="wrap_content"

android:gravity="center_horizontal"

>

<TextView

android:id="@+id/textView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="20dp"

android:text="TextView_Relative"

android:textSize="24sp"/>

<EditText

android:id="@+id/editText"

android:layout_width="300dp"

android:layout_height="wrap_content"

android:layout_below="@+id/textView"

android:hint="@string/divide"/>

</RelativeLayout>

---------------------------------------------------------------

//include_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>

<android.support.v7.widget.Toolbar

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:id="@+id/tb_toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

android:background="#00f"

app:theme="@style/AppTheme"

app:title="这是一个 ToolBar"app:titleTextColor="@android:color/white"/>

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

>

<!--测试 layout 和<include>都设置 ID 的情况-->

<include

android:id="@+id/tb_toolbar"

layout="@layout/include_toolbar"/>

<!--如果只有单个 include 这样写就可以,加载的布局的子 View,直接 findViewByID 就能找

到-->

<include layout="@layout/include_text"/>

<!--如果有多个 include,需要添加 ID 属性-->

<include

android:id="@+id/include_text1"

layout="@layout/include_text"/>

<!--这个 layout 用 RelativeLayout 实现-->

<!--如果要使用 layout_margin 这样的属性,要同时加上 layout_w/h 属性,不然没反应-->

<include

android:id="@+id/include_text2"

layout="@layout/include_text_relative"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="50dp"/>

</LinearLayout>

private void initView() {

//如果 include 布局根容器和 include 标签中的 id 设置的是不同的值,这里获取的

mToolbar 值将为 nullToolbar mToolbar = (Toolbar) findViewById(R.id.tb_toolbar)

setSupportActionBar(mToolbar)

//普通 include 标签用法,直接拿子 View 属性实现

TextView textView = (TextView) findViewById(R.id.textView)

textView.setText("不加 ID 实现的 include 标签")

//多个 include 标签用法,添加 ID,findViewByID 找到 layout,再找子控件

View view_include = findViewById(R.id.include_text1)

TextView view_include_textView = (TextView) view_include.findViewById(R.id.textView)

view_include_textView.setText("加了 ID 实现的 include 标签")

//多个 include 标签用法,添加 ID,findViewByID 找到 layout,再找子控件

View view_include_Relative = findViewById(R.id.include_text2)

TextView view_textView_relative =(TextView) view_include_Relative.findViewById(R.id.textView)

view_textView_relative.setText("加了 ID 实现的 include 标签(RelaviteLayout)")

}

include 标签 Demo 效果图

==include 使用注意==

merge标签主要用于辅助include标签,在使用include后可能导致布局嵌套过

多,多余的 layout 节点或导致解析变慢(可通过 hierarchy viewer 工具查看布

局的嵌套情况)官方文档说明:merge 用于消除视图层次结构中的冗余视图,例如根布局是

Linearlayout,那么我们又 include 一个 LinerLayout 布局就没意义了,反而会

减慢 UI 加载速度

merge 标签常用场景: .

根布局是 FrameLayout 且不需要设置 background 或 padding 等属性,可

以用merge代替,因为 Activity的 ContentView 父元素就是FrameLayout,

所以可以用 merge 消除只剩一个.

.某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,

这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中.

.自定义 View 如果继承 LinearLayout(ViewGroup),建议让自定义 View 的

布局文件根布局设置成 merge,这样能少一层结点.

.merge 标签使用:

在 XML 布局文件的根布局如 RelativeLayout 直接改成 merge 即可

merge 标签使用前后 Hierarchy Viewer 截图

FrameLayout 替换 merge 前

FrameLayout 替换 merge 后

include 标签对应 layout 根布局 替换 merge 前

include 标签对应 layout 根布局 替换 merge 后

==merge 使用注意==

ViewStub 标签最大的优点是当你需要时才会加载,使用它并不会影响 UI 初始

化时的性能.各种不常用的布局像进度条、显示错误消息等可以使用 ViewStub

标签,以减少内存使用量,加快渲染速度.ViewStub 是一个不可见的,实际上是把

宽高设置为 0 的 View.效果有点类似普通的 view.setVisible(),但性能体验提高

不少

第一次初始化时,初始化的是 ViewStub View,当我们调用 inflate()或

setVisibility()后会被 remove 掉,然后在将其中的 layout 加到当前 view

hierarchy 中

ViewStub 官方文档链接

//官方例子

<ViewStub

android:id="@+id/stub_import"

<!--android:inflateId:重写 ViewStub 的父布局控件的 Id-->

android:inflatedId="@+id/panel_import"

<<!--android:layout:设置 ViewStub 被 inflate 的布局-->

android:layout="@layout/progress_overlay"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_gravity="bottom" />

-------------------------------------------------//当你想加载布局时,可以使用下面其中一种方法:

((ViewStub)

findViewById(R.id.stub_import)).setVisibility(View.VISIBLE)

// or

View importPanel = ((ViewStub)

findViewById(R.id.stub_import)).inflate()

判断 ViewStub(做单例)是否已经加载过:

1. 如果通过 setVisibility 来加载,那么通过判断可见性即可

2. 如果通过 inflate()来加载,判断 ViewStub 的 ID 是否为 null 来判断

(findViewById(…))

public class ViewStubActivity extends AppCompatActivity

implements View.OnClickListener, ViewStub.OnInflateListener {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState)setContentView(R.layout.activity_view_stub)

}

private View networkErrorView

private void showNetError() {

// not repeated infalte

if (networkErrorView != null) {

//setVisibility()方式加载布局,加载次数不限

networkErrorView.setVisibility(View.VISIBLE)

return

}

//inflate()方式加载布局,只能加载一次

ViewStub stub = (ViewStub)

findViewById(R.id.network_error_layout)

stub.setOnInflateListener(this)networkErrorView = stub.inflate()

Button networkSetting = (Button)

networkErrorView.findViewById(R.id.network_miss)

networkSetting.setOnClickListener(this)

Button refresh = (Button)

findViewById(R.id.network_refresh)

refresh.setOnClickListener(this)

}

private void showNormal() {

if (networkErrorView != null) {

networkErrorView.setVisibility(View.GONE)

}

}

public void show(View view) {showNetError()

}

public void refresh(View view) {

showNormal()

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.network_miss:

Toast.makeText(this, "network_miss",

Toast.LENGTH_SHORT).show()

break

case R.id.network_refresh:

Toast.makeText(this, "network_refresh",

Toast.LENGTH_SHORT).show()break

}

}

/**

*

* @param stub 当前待 inflate 的 ViewStub 控件

* @param inflated 当前被 inflate 的 View 视图

*/

@Override

public void onInflate(ViewStub stub, View inflated) {

}

}

ViewStub 标签 Demo 效果图:

ViewStub 标签使用前后 Hierarchy Viewer 截图

ViewStub 标签使用前:

ViewStub 标签使用后:

==ViewStub 标签使用注意==

扩展:

Space 组件

在 ConstraintLayout 出来前,我们写布局都会使用到大量的 margin 或

padding,但是这种方式可读性会很差,加一个布局嵌套又会损耗性能

鉴于这种情况,我们可以使用space,使用方式和View一样,不过主要用来占位置,

不会有任何显示效果


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11432420.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存