CPU 与网络等是属于 Background Process,若要优化,须要设法减小、延迟、合并 Background Process。html
从 API 23 开始, Android 提供了这两种模式以延长电池寿命,是 Android 系统的大方针。Doze 就是将一些 Wakelocks、网络、Jobs/Syncs、Alarms、GPS/Wifi 禁止/延迟,仅在须要唤醒这些东西时即到维护窗口时才唤醒。App Standby 是应用级别的,细分到每个应用中的,应用未使用一段时间后(即没有 foreground process 时)就会进入 App Standby,进入此状态后 App 就不能访问网络而且 Jobs/Syncs 都会受到延迟。java
固然,启用 Foreground Service 就不会受到 Doze 和 App Standby 的影响。同时,在 AOSP 中这两个模式是关闭的,具体须要看看手机厂商有没有开启,提起这个只是给到你们一个官方的方案来引导咱们作本身的方案。android
developer.android.google.cn/training/mo…git
若要进行功耗优化,则须要设法减小、延迟、合并 Background Process。经过 Doze 则是对 Background Process 进行合并,即合并到维护窗口时;经过 App Standby 则是对 Backgroud Process 进行延迟,即延迟到"使用"状态下或充电状态下。这些是系统级别的优化,而应用级别的优化则是在平时的积累中进行的,好比对耗电功能进行优化,原则上与上面一致,即减小、延迟、合并这些功耗大的功能:github
/** * This method checks for power by comparing the current battery state against all possible * plugged in states. In this case, a device may be considered plugged in either by USB, AC, or * wireless charge. (Wireless charge was introduced in API Level 17.) */
private boolean checkForPower() {
// It is very easy to subscribe to changes to the battery state, but you can get the current
// state by simply passing null in as your receiver. Nifty, isn't that?
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(null, filter);
// There are currently three ways a device can be plugged in. We should check them all.
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_USB);
boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
boolean wirelessCharge = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
wirelessCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_WIRELESS);
}
return (usbCharge || acCharge || wirelessCharge);
}
复制代码
Battery Historian 是 Android 5.0 以后引入的一个获取设备电量消耗信息的图形化工具,可以直观展现手机电量消耗。网络
Battery_Historian_Tool使用说明数据结构
JobScheduler:系统利用这些触发的设置,合并相同的 background process,从而优化内存和电池性能。并发
除避免内存泄漏外还有其余内存优化手段:less
用 JobScheduler 替代 Service。若必须使用 Service,最好用 IntentService 限制服务寿命,全部请求完成后会自动中止。ide
使用 SparseArray、SparseBooleanArray、LongSparseArray 代替 HashMap 等数据结构。
必要时释放内存:
import android.content.ComponentCallbacks2;
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
/** * 当UI不可见时或系统资源不足时释放内存 * @param level 引起的与内存相关的事件 */
public void onTrimMemory(int level) {
// 肯定引起了哪一个生命周期或系统事件
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
/* 释放一些不必的内存资源。如今用户界面已移至后台 */
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
/* 释放应用不须要的内存。 应用程序运行时,设备内存不足。 引起的事件表示与内存相关的事件的严重性。 若是事件是TRIM_MEMORY_RUNNING_CRITICAL,那么系统将开始杀死后台进程。 */
break;
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
/* 释放尽量多的内存。 该应用程序位于LRU列表中而且系统内存不足。 引起的事件代表应用程序位于LRU列表中的位置。 若是引起的事件是 TRIM_MEMORY_COMPLETE, 这一进程将是最早终止的进程之一。 */
break;
default:
/* 释听任何非关键数据结构。 应用程序从系统接收到一个没法识别的内存级别值。 将其视为通常的低内存消息。 */
break;
}
}
}
复制代码
检查当前使用了多少内存,作好保护去释放一些次要资源以防 OOM:
public void doSomethingMemoryIntensive() {
// 在作一些须要大量内存的事情以前检查设备是否处于低内存状态
ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();
if (!memoryInfo.lowMemory) {
// 当前处于低内存状态 ...
}
}
// 获取 MemoryInfo
private ActivityManager.MemoryInfo getAvailableMemory() {
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
复制代码
优化布局层次、避免自定义组件中 onDraw 建立大量临时对象。