1.intent傳值
Activity 間的數(shù)據(jù)通信煤禽,對(duì)于數(shù)據(jù)量比較大的享潜,避免使用 Intent + Parcelable
的方式,可以使用 EventBus布近、RxJava 等替代亩码,以免造成 TransactionTooLargeException丁恭。
- ActivityNotFoundException
Activity 間通過(guò)隱式 Intent 的跳轉(zhuǎn),在發(fā)出 Intent 之前盡可能通過(guò) resolveActivity
檢查疚俱,避免找不到合適的調(diào)用組件式塌,造成 ActivityNotFoundException 的異常武通。
正確做法:
Intent intent = new Intent(“Action”);
intent.setDataAndType("Data", "Type");
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
}
- 避免主線(xiàn)程執(zhí)行耗時(shí)操作
在主線(xiàn)程執(zhí)行耗時(shí)操作,會(huì)導(dǎo)致 UI 不流暢或ANR珊搀。下面情況應(yīng)多加注意:
避免在 BroadcastReceiver#onReceive()中執(zhí)行耗時(shí)操作冶忱,如果有耗時(shí)工作,
應(yīng)該創(chuàng)建 IntentService 完成境析,而不應(yīng)該在 BroadcastReceiver 內(nèi)創(chuàng)建子線(xiàn)程去做囚枪。
@Override
public void onReceive(Context context, Intent intent) {
Intent intent = new Intent();
intent .setClass(this, TestService.class);
context .startService(intent );
}
public class TestService extends IntentService {
......
@Override
protected void onHandleIntent(Intent intent) {
synchronized (this) {
try {
......
} catch (Exception e) {
}
避免在 Service.onStartCommand()/onBind()方法中執(zhí)行耗時(shí)操作派诬,如果確實(shí)有需求,應(yīng)改用 IntentService 或采用其他異步機(jī)制完成链沼。
- 廣播的效率與安全處理
避免使用隱式 Intent 廣播敏感信息默赂,信息可能被其他注冊(cè)了對(duì)應(yīng)
BroadcastReceiver 的 App 接收。
通過(guò) Context.sendBroadcast()發(fā)送的隱式廣播會(huì)被所有感興趣的 receiver 接收括勺,惡意應(yīng)用注冊(cè)監(jiān)聽(tīng)該廣播的 receiver 可能會(huì)獲取到 Intent 中傳遞的敏感信息缆八,并進(jìn)行其他危險(xiǎn)操作。
通過(guò) Context.sendOrderedBroadcast()方法發(fā)送的有序廣播疾捍,優(yōu)先級(jí)較高的惡意 receiver 可能直接丟棄該廣播奈辰,造成服務(wù)不可用,或者向廣播結(jié)果塞入惡意數(shù)據(jù)乱豆。
如果廣播僅限于應(yīng)用內(nèi)奖恰,應(yīng)該使用 LocalBroadcastManager.sendBroadcast()實(shí)
現(xiàn),避免敏感信息外泄和 Intent 攔截的風(fēng)險(xiǎn)宛裕,也提高了廣播接收的效率瑟啃。
import android.support.v4.content.LocalBroadcastManager;
/**
* 類(lèi):MessageTip 消息提醒類(lèi)
* 了解更多,請(qǐng)參考《消息系統(tǒng)實(shí)現(xiàn)方案》
* 作者: qxc
* 日期:2017/9/1.
*/
public class MessageTip {
/**
* 消息提醒類(lèi)實(shí)例
*/
private static MessageTip messageTip;
/**
* 本地廣播數(shù)據(jù)類(lèi)型實(shí)例
*/
private LocalBroadcastManager localBroadcastManager;
......
/**
* 檢查消息
* @param context 上下文
*/
public void checkMessage(final Context context){
//獲得本地廣播實(shí)例
if(localBroadcastManager==null) {
localBroadcastManager = LocalBroadcastManager.getInstance(context);
}
//定時(shí)刷新數(shù)據(jù)
......
}
/**
* 獲得消息提醒數(shù)量并發(fā)送本地廣播
*/
public void getMessageTipNum(Context context){
//判斷是否顯示消息提示數(shù)量
if(AppTools.getCurrUser().getUid()==0 || !(NetWorkUtils.getInstance().isNetworkAvailable(context))){
//發(fā)送本地廣播
if(localBroadcastManager != null) {
Intent intent = new Intent();
intent.setAction(ACTIONMESSAGETIP);
intent.putExtra(KEYISSHOWTIPNUM, isShowTipNum);
localBroadcastManager.sendBroadcast(intent);
}
return;
}
//獲得用戶(hù)消息數(shù)量
getUserMessageNum(context);
}
......
Activity或者Fragment中動(dòng)態(tài)注冊(cè)BroadCastReceiver時(shí)揩尸,registerReceiver()和 unregisterReceiver()要成對(duì)出現(xiàn)!!!
- Activity釋放資源的時(shí)機(jī)
不要在 Activity#onDestroy()內(nèi)執(zhí)行釋放資源的工作蛹屿,例如一些工作線(xiàn)程的
銷(xiāo)毀和停止,因?yàn)?onDestroy()執(zhí)行的時(shí)機(jī)可能較晚岩榆±澹可根據(jù)實(shí)際需要,在
Activity#onPause()/onStop()中結(jié)合 isFinishing()的判斷來(lái)執(zhí)行朗恳。
6.Fragment
如非必須,避免使用嵌套的 Fragment载绿。Fragment 嵌套使用會(huì)有一些坑粥诫,容易出現(xiàn) bug。
onActivityResult()方法的處理錯(cuò)亂崭庸;
內(nèi)嵌的 Fragment 可能收不到該方法的回調(diào)怀浆,需要由宿主 Fragment 進(jìn)行轉(zhuǎn)發(fā)處理;
被繼承的 setRetainInstance()怕享,導(dǎo)致在 Fragment 重建時(shí)多次觸發(fā)不必要的邏輯执赡。
添加Fragment 時(shí),確保 FragmentTransaction#commit() 在Activity#onPostResume()或者 FragmentActivity#onResumeFragments()內(nèi)調(diào)用函筋。
Activity可能因?yàn)楦鞣N原因被銷(xiāo)毀沙合,Android支持頁(yè)面被銷(xiāo)毀前通過(guò)
Activity#onSaveInstanceState() 保 存 自 己 的 狀 態(tài) 。 但 如 果FragmentTransaction.commit()發(fā)生在 Activity 狀態(tài)保存之后跌帐,就會(huì)導(dǎo)致 Activity 重建首懈、恢復(fù)狀態(tài)時(shí)無(wú)法還原頁(yè)面狀態(tài)绊率,從而可能出錯(cuò)。
為了避免給用戶(hù)造成不好的體驗(yàn)究履,系統(tǒng)會(huì)拋出 IllegalStateExceptionStateLoss 異常滤否。
推薦的做法是在 Activity 的onPostResume() 或 onResumeFragments() ( 對(duì) FragmentActivity ) 里
執(zhí)行FragmentTransaction.commit(),如有必要也可在 onCreate()里執(zhí)行最仑。
7.顯示調(diào)用service等組件
用顯式 Intent 啟動(dòng)或者綁定 Service藐俺,且不要為服務(wù)聲明 Intent Filter,保證應(yīng)用的安全性泥彤。
如果確實(shí)需要使用隱式調(diào)用欲芹,則可為 Service 提供 Intent Filter并從 Intent 中排除相應(yīng)的組件名稱(chēng),
但必須搭配使用 Intent#setPackage()方法設(shè)置Intent 的指定包名全景,這樣可以充分消除目標(biāo)服務(wù)的不確定性耀石。
Service 需要以多線(xiàn)程來(lái)并發(fā)處理多個(gè)啟動(dòng)請(qǐng)求,建議使用 IntentService爸黄;
8.Activity效率
當(dāng)前Activity的onPause方法執(zhí)行結(jié)束后才會(huì)執(zhí)行下一個(gè)Activity的onCreate方法滞伟,
所以在 onPause 方法中不適合做耗時(shí)較長(zhǎng)的工作,這會(huì)影響到頁(yè)面之間的跳轉(zhuǎn)效率炕贵。
- Adapter 滑動(dòng)錯(cuò)亂
使用 Adapter 的時(shí)候梆奈,如果使用了 ViewHolder 做緩存,在 getView()的方法中無(wú)論這項(xiàng) convertView 的
每個(gè)子控件是否需要設(shè)置屬性(比如某個(gè) TextView設(shè)置的文本可能為 null称开,某個(gè)按鈕的背景色為透明亩钟,某控件的顏色為透明等),
都需要為其顯式設(shè)置屬性(Textview 的文本為空也需要設(shè)置 setText("")鳖轰,背景透明也需要設(shè)置)清酥,
否則在滑動(dòng)的過(guò)程中,因?yàn)?adapter item 復(fù)用的原因蕴侣,會(huì)出現(xiàn)內(nèi)容的顯示錯(cuò)亂焰轻。
10.日志輸出
不要使用 System.out.println 打印,盡量使用 log昆雀,因?yàn)閘og更可控一些:
log可分等級(jí)輸出
log可過(guò)濾
log可檢索
注意:log的tag不能為空辱志,即“”,因?yàn)槿罩镜?tag 是空字符串沒(méi)有任何意義狞膘,不利于過(guò)濾日志揩懒。
......
第一篇: 安卓編程技巧總結(jié)(1) 資源與UI布局處理
http://www.reibang.com/p/ff97b15d5c9d
第二篇: 安卓編程技巧總結(jié)(2) 基礎(chǔ)組件開(kāi)發(fā)
http://www.reibang.com/p/b05752377887
第三篇:安卓編程技巧總結(jié)(3) 進(jìn)程與線(xiàn)程處理
http://www.reibang.com/p/7d05c8a368bd
第四篇:安卓編程技巧總結(jié)(4) 數(shù)據(jù)文件處理
http://www.reibang.com/p/0515df3b697d
第五篇:安卓編程技巧總結(jié)(5) 圖片處理
http://www.reibang.com/p/76690b2ba310
第六篇:安卓編程技巧總結(jié)(6) APP安全分析
http://www.reibang.com/p/4347ff392122