为什么要省电?
电池的容量没有大幅度的提升,使用Android手机会越来越耗电,电池的可用时间极大的缩短。
有哪些地方在耗电?
1. 网络、GPS、传感器和CPU等
2. 不合理的使用屏幕唤醒wakelock
3. 后台应用过多,频繁进行数据更新操作
4. 不合理的设置屏幕亮度值和屏幕超时值等
5. 启动多个service6. 创建大量的临时对象
怎样编写更省电?
只在WiFi或3G下使用网络
// 只在WiFi或3G下使用网络
NetworkInfo info;
int netType = info.getType();
int netSubtype = info.getSubtype();
if (netType == ConnectivityManager.TYPE_WIFI) {
return info.isConnected();
} else if (netType == ConnectivityManager.TYPE_MOBILE
&& netSubtype == TelephonyManager.NETWORK_TYPE_UMTS
&& !mTelephony.isNetworkRoaming()) {
return info.isConnected();
} else {
return false;
}
设置网络连接超时
设置网络连接超时时间
正确
URL httpUrl = new URL(url);
HttpURLConnection connection =
(HttpURLConnection)httpUrl.openConnection();
connection.setConnectTimeout(5000) // unit milliseconds
错误
URL httpUrl = new URL(url);
HttpURLConnection connection =
(HttpURLConnection)httpUrl.openConnection();
//connection.setConnectTimeout(timeout) //default 0s
尽量使用GZIP进行文本数据的传输
尽量使用GZIP进行文本数据传输
import java.util.zip.GZIPInputStream;
HttpGet request = new
HttpGet("http://example.com/gzipcontent");
HttpResponse resp = new
DefaultHttpClient().execute(request);
HttpEntity entity = response.getEntity();
InputStream compressed = entity.getContent();
InputStream rawData = new
GZIPInputStream(compressed);
缓存文件到本地
缓存文件到本地
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(
CoreConnectionPNames.SO_TIMEOUT, 5000);
HttpGet httpget = new HttpGet("http://example.com/
pictures");
HttpResponse response = httpclient.execute(httpget);
Header[] header = response.getHeaders("ETag");
if(header != null && header.length > 0){
String catch = header[0].toString();
}
减少连接次数
重用已经存在的网络连接比新建立一个连接通常更有效率的由于http协议的“三次握手”
判断GPS开关状态
判断GPS开关状态
正确
String provider = Settings.Secure.getString(
context.getContentResolver(),Settings.Secure.LOCATION_PROVIDE
RS_ALLOWED);
if (provider != null && provider.contains("gps")) {
return true;
}
错误
LocationManager lManager = (LocationManager)
context.getSystemService(Context.LOCATION_SERVICE);
lManager .isProviderEnabled(LocationManager.GPS_PROVIDER);
Sensor
Sensor
正确
@Override
protected void onResume() {
mSensorManager.registerListener(this,mSensorManager.getDefaultS
ensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR
_DELAY_NORMAL);
}
@Override
protected void onPause() {
mSensorManager.unregisterListener(this);
}
Sensor
错误
public final class BkService extends Service implements
SensorEventListener{
@Override
protected void onStart() {
mSensorManager.registerListener(this,mSensorManager.getDefaultS
ensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR
_DELAY_NORMAL);
}
@Override
protected void onDestroy() {
mSensorManager.unregisterListener(this);
}
调整定时更新的频率
调整定时更新的频率
int alarmType = AlarmManager.ELAPSED_REALTIME;
long interval = AlarmManager.INTERVAL_HOUR;
long start = System.currentTimeMillis() + interval;
alarmManager.setInexactRepeating(alarmType, start,
interval, pi);
如果可以,请设置提醒的类型为ELAPSED_REALTIME or RTC
而不是_WAKEUP。这样在系统睡眠的时候不会唤醒CPU。
回收Java对象
回收java对象
有些对象的回收不能依赖于JAVA的GC
XmlPullParserFactory and BitmapFactory
Matcher.reset(newString) for regex
StringBuilder.setLength(0)
使用软引用
使用软引用
正确
ApplicationInfo ai;
PackageManager mPm;
ai = mPm.getApplicationInfo(app.pkgName, 0);
app.icon = new SoftReference<Drawable>(ai.loadIcon(mPm));
holder.iconView.setImageDrawable(app.icon.get());
错误
ai = mPm.getApplicationInfo(app.pkgName, 0);
Drawable icon= ai.loadIcon(mPm);
holder.iconView.setImageDrawable(icon);
按需操控广播接受者
按需操控广播接收者
ComponentName receiver = new ComponentName(context,
myReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_EN
ABLED, PackageManager.DONT_KILL_APP)
数据库使用事务
数据库使用事务
SQLiteDatabase db = mHelper.getWritableDatabase();
db.beginTransaction();
try{
for (int i = 0; i < usageHisList.size(); i++) {
db.insert(table,null, values);
}
db.setTransactionSuccessful();
}catch(Exception ex){
}
db.endTransaction();
动画
正确
@Override
protected void onResume() {
image.startAnimation(mChargingAnim); //开始动画
}
@Override
protected void onPause() {
image.clearAnimation(); //结束动画
}
<pre name="code" class="java">错误
@Override
protected void onCreate(Bundle b) {
image.startAnimation(mChargingAnim); //开始动画
}
@Override
protected void onDestory() {
image.clearAnimation(); //结束动画
}
尽量使用Application Context
尽量使用 application context
在android中有两种context,一种是 application context,一种是activity context。
public class BatteryActivity extends Activity {
private static Drawable mBackground;
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this.getApplicationContext());
label.setText("It is good !");
if (mBackground == null) {
mBackground = getDrawable(R.drawable.battery_info);
}
label.setBackgroundDrawable(mBackground);//drawable attached to a view
setContentView(label);
}
}
尽量减少布局层次
尽量减少布局层次
1. Textview +Imageview → Textview
+icon(android:drawableXXX)
2. 多个LinearLayout→单个RelativeLayout
3. 通过<include /> 标签来重用layout代码
4. 使用<merge /> 标签来减少视图层级结构
性能分析工具介绍
tools/hierarchyviewer.bat查看UI布局设计结构和各种属性的信息
tools/lint.bat分析布局文件合理性,给出优化建议
tools/traceview.bat查看函数以及子函数运行时间
tools/systrace/systrace.py可以从Linux内核中直接收集数据,来帮助诊断性能问题