下面是些具体的tips:
内存优化;
1.共享内存:
2.当UI不可见时,释放不必要的Ui资源:
在activity中重写 onTrimMemory()监听当level=TRIM_MEMORY_UI_HIDDEN时释放UI资源;这雨在OnStop中是否资源不同。
onTrimMemory()的几个回调方法,
TRIM_MEMORY_BACKGROUND
The system is running low on memory and your process is near the beginning of the LRU list. Although your app process is not at a high risk of being killed, the system may already be killing processes in the LRU cache. You should release resources that are easy to recover so your process will remain in the list and resume quickly when the user returns to your app.
TRIM_MEMORY_MODERATE
The system is running low on memory and your process is near the middle of the LRU list. If the system becomes further constrained for memory, there's a chance your process will be killed.
TRIM_MEMORY_COMPLETE
The system is running low on memory and your process is one of the first to be killed if the system does not recover memory now. You should release everything that's not critical to resuming your app state.
3.你应该为你的app使用多少内存getMemoryClass()获取到heap Size的值,然后在开发app的时候保证开销在这个值之下
4.在使用bitmaps时避免消耗内存
5.使用优化了的数据容器:
一般使用HashMap,但是该集合太耗内存,使用 SparseArray, SparseBooleanArray,和 LongSparseArray更高效
6.考虑内存开销:
避免使用枚举,可以用静态类来代替每一个类都要占用500个字节,占用内存12-16字节
7.如无必要,不要使用抽象类
8.使用protobufs序列化数据
9.不要使用注解框架
10.注意考量你引入的第三方库,不要仅仅使用库的某一个功能而将整个库都copy进来了。
11.使用ProGuard来移除你的工程中没有使用到的代码
12.在打包签名之后,请使用zipalign命令zipalign -f -v 4 signed.apk aligned.apk
13.在app功能完善后,可以考虑开始分析RAM使用情况,使用DDMS中的 Allocation Tracker等工具监控内存使用情况。
14.优化你的UI,使用DDMMS中的Hierarchy Viewer来分析布局,优化布局。
15.使用多进程,一般而言一个app是只占用一个进程的。比如一个应用是播放音乐的,我们可以将该app分为2个进程,一个用来
加载处理UI部分,一个服务专门用来播放歌曲,该服务是另起的一个进程。
<service android:name=".PlaybackService"
android:process=":background" />
性能建议:一些平常编程中需要注意的地方
这里有2个根本的原则就是:能不做的事情就不要做,能不分配额外的内存就尽量避免。
1.避免创建不必要的对象
2.对常量使用静态final
3.避免设置过多的GET,SET方法,如果要访问,直接用public修饰
4.使用增强for循环
5.避免使用float或者double,使用int
6.熟练使用android或者java中自带的方法,避免重复造轮子
7.使用Native Method要注意,并不能提高效率很多。
布局性能优化:
1.使用Hierarchy Viewer检查你的布局,它会分层次的展开你的布局。每个布局上都有3个值Measure,Layout,Draw使用的时间。
当图形层次上出现红色点的时候,就应该考虑修订布局。一般使用relativelayout会减少布局层次;使用linearlayout就要多点层次,而且如果你用了weight属性在linearlayout里,而且作为listview的条目,那么性能会更低。
2.Lint优化布局,如果你的根布局可以是Framelayout,而且根布局不提供其他属性设置。那么可以去掉根布局使用Merge
3.重用布局文件使用include
titlebar.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/titlebar_bg">
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gafricalogo" />
</FrameLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/app_bg"
android:gravity="center_horizontal">
<include layout="@layout/titlebar"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
android:padding="10dp" />
...
</LinearLayout>
也可以为重用布局的时候,重新指定宽高:
<include
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/title"/>
4.ViewStub,仅仅在该view需要显示的时候才inflate;不支持merge
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
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();
5.使用listview和gridview时使用viewholder,当然如果你用recyclerview就不必了。
电池优化;
网络数据传输:保证网络数据请求在某一个时间段集中处理,不要太零散,这会导致不停唤醒cpu,唤醒网络浪费电。
请求前判断网络连接
1.收集网络传输数据;
public static final int USER_INITIATED = 0x1000;
public static final int APP_INITIATED = 0x2000;
public static final int SERVER_INITIATED =0x3000;
找到你app中执行网络请求的地方:
if (BuildConfig.NETWORK-TEST && Build.VERSION.SDK_INT >= 14) {
try {
TrafficStats.setThreadStatsTag(USER_INITIATED);
// make network request using HttpClient.execute()
} finally {
TrafficStats.clearThreadStatsTag();
}
}
GCM Network Manager,Job Scheduler,Sync Adapter for scheduled syncs
使用 GCM发送更新
监控电池状态来改变后台刷新频率
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
<receiver android:name=".PowerConnectionReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
</receiver>
public class PowerConnectionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
}
}
获取电池电量:
int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale;
监控电池电量的显著变化
<receiver android:name=".BatteryLevelReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
<action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
</intent-filter>
</receiver>
监控网络连接情况:
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork.isConnectedOrConnecting();
确定互联网连接的类型
boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
*/