本篇繼續上一篇《阿里巴巴Android編碼規範》閱讀紀要(一) ,仍是建議各位同窗有時間完整閱讀一下《阿里巴巴Android編碼規範》,若是實在沒時間,就看個人本系列博客吧,主要摘錄一些我的認爲比較重要的地方。
html
UI 與佈局部分java
1,不能使用 ScrollView 包裹 ListView/GridView/ExpandableListVIew;由於這樣會把 ListView 的全部 Item 都加載到內存中,要消耗巨大的內存和 cpu 去繪製圖面。android
說明:web
ScrollView 中嵌套 List 或 RecyclerView 的作法官方明確禁止。除了開發過程當中遇到的各類視覺和交互問題,這種作法對性能也有較大損耗。ListView 等 UI 組件自身有垂直滾動功能,也沒有必要在嵌套一層 ScrollView。目前爲了較好的 UI 體驗,更貼近 Material Design 的設計,推薦使用 NestedScrollView。算法
正例:數據庫
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.v4.widget.NestedScrollView>
<LinearLayout>
<ImageView/>
...
<android.support.v7.widget.RecyclerView/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
反例:安全
<ScrollView> <LinearLayout> <TextView/> ... <ListView/> <TextView />
</LinearLayout> </ScrollView>
進程、線程與消息通訊部分app
1,新建線程時,必須經過線程池提供(AsyncTask 或者 ThreadPoolExecutor或者其餘形式自定義的線程池),不容許在應用中自行顯式建立線程。異步
說明ide
使用線程池的好處是減小在建立和銷燬線程上所花的時間以及系統資源的開銷,解決資源不足的問題。若是不使用線程池,有可能形成系統建立大量同類線程而致使消耗完內存或者「過分切換」的問題。另外建立匿名線程不便於後續的資源使用分析,對性能分析等會形成困擾。
2,線程池不容許使用 Executors 去建立,而是經過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同窗更加明確線程池的運行規則,規避資源耗盡的風險。
說明:
Executors 返回的線程池對象的弊端以下:
1) FixedThreadPool 和 SingleThreadPool : 允 許 的 請 求 隊 列 長 度 爲Integer.MAX_VALUE,可能會堆積大量的請求,從而致使 OOM;
2) CachedThreadPool 和 ScheduledThreadPool :容許的建立線程數量爲Integer.MAX_VALUE,可能會建立大量的線程,從而致使 OOM。
關於線程池學習能夠參考我以前寫的兩篇博客java線程池技術(一):ThreadFactory與BlockingQueue 與java線程池技術(二): 核心ThreadPoolExecutor介紹。
3,不要在非 UI 線程中初始化 ViewStub,不然會返回 null。
4,禁止在多進程之間用SharedPreferences共享數據,雖然能夠(MODE_MULTI_PROCESS),但官方已不推薦。
文件與數據庫部分
1,SharedPreference提交數據時,儘可能使用Editor#apply() ,而非Editor#commit()。通常來說,僅當須要肯定提交結果,並據此有後續操做時,才使用 Editor#commit()。
說明:
SharedPreference 相關修改使用 apply 方法進行提交會先寫入內存,而後異步寫入磁盤,commit 方法是直接寫入磁盤。若是頻繁操做的話 apply 的性能會優於 commit,apply 會將最後修改內容寫入磁盤。可是若是但願馬上獲取存儲操做的結果,並據此作相應的其餘操做,應當使用 commit。
正例:
public void updateSettingsAsync() { SharedPreferences mySharedPreferences = getSharedPreferences("settings", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = mySharedPreferences.edit(); editor.putString("id", "foo"); editor.apply(); } public void updateSettings() { SharedPreferences mySharedPreferences = getSharedPreferences("settings", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = mySharedPreferences.edit(); editor.putString("id", "foo"); if (!editor.commit()) { Log.e(LOG_TAG, "Failed to commit setting changes"); }
反例:
editor.putLong("key_name", "long value");
editor.commit();
2,大數據寫入數據庫時,請使用事務或其餘可以提升 I/O 效率的機制,保證執行速度。
正例:
public void insertBulk(SQLiteDatabase db, ArrayList<UserInfo> users) {
db.beginTransaction(); try { for (int i = 0; i < users.size; i++) { ContentValues cv = new ContentValues(); cv.put("userId", users[i].userId); cv.put("content", users[i].content); db.insert(TUserPhoto, null, cv); } // 其餘操做 db.setTransactionSuccessful(); } catch (Exception e) { // TODO } finally { db.endTransaction(); } }
3,執行 SQL 語句時,應使用 SQLiteDatabase#insert()、update()、delete(),不要使用 SQLiteDatabase#execSQL(),以避免 SQL 注入風險。
Bitmap、Drawable 與動畫
1,加載大圖片或者一次性加載多張圖片,應該在異步線程中進行。圖片的加載,涉及到 IO 操做,以及 CPU 密集操做,極可能引發卡頓。
2,png 圖片使用 tinypng 或者相似工具壓縮處理,減小包體積。
我的簡要說明:TinyPng官網地址:https://tinypng.com/。TinyPng可以對PNG和JPG/JPEG格式圖片進行有效壓縮,圖片體積大幅減少,可達六七成,而且失真較小。
3,使用完畢的圖片,應該及時回收,釋放寶貴的內存。
正例:
Bitmap bitmap = null; loadBitmapAsync(new OnResult(result){ bitmap = result; }); ...使用該 bitmap... //使用結束,在 2.3.3 及如下須要調用 recycle()函數,在 2.3.3 以上 GC 會自動管理,除非你明確不須要再用。 if (Build.VERSION.SDK_INT <= 10) { bitmap.recycle(); } bitmap = null;
4,在 Activity.onPause()或 Activity.onStop()回調中,關閉當前 activity 正在執行的的動畫。
正例:
public class MyActivity extends Activity { ImageView mImageView; Animation mAnimation; Button mBtn; /** 首次建立 activity 時調用 */ @Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); mImageView = (ImageView)findViewById(R.id.ImageView01); mAnimation = AnimationUtils.loadAnimation(this, R.anim.anim); mBtn= (Button)findViewById(R.id.Button01); mBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImageView.startAnimation(mAnimation); } }); } public void onPause() { //頁面退出,及時清理動畫資源 mImageView.clearAnimation() } }
5,使用 ARGB_565 代替 ARGB_888,在不怎麼下降視覺效果的前提下,減小內存佔用。
說明:
android.graphics.Bitmap.Config 類中關於圖片顏色的存儲方式定義:
1)ALPHA_8 表明 8 位 Alpha 位圖;
2)ARGB_4444 表明 16 位 ARGB 位圖;
3)ARGB_8888 表明 32 位 ARGB 位圖;
4)RGB_565 表明 8 位 RGB 位圖。
位圖位數越高,存儲的顏色信息越多,圖像也就越逼真。大多數場景使用的是 ARGB_8888 和 RGB_565,RGB_565 可以在保證圖片質量的狀況下大大減小內存的開銷,是解決oom的一種方法。
可是必定要注意 RGB_565 是沒有透明度的,若是圖片自己須要保留透明度,那麼就不能使用 RGB_565。
正例:
Config config = drawableSave.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 :
Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
反例:
Bitmap newb = Bitmap.createBitmap(width, height, Config.ARGB_8888);
安所有分
1,將 android:allowbackup 屬性設置爲 false,防止 adb backup 導出數據。
說明:
在 AndroidManifest.xml 文件中爲了方便對程序數據的備份和恢復在 Android API level 8 之後增長了 android:allowBackup 屬性值。默認狀況下這個屬性值爲 true,故當 allowBackup 標誌值爲 true 時,便可經過 adb backup 和 adb restore 來備份和恢復應用程序數據。
正例:
<application android:allowBackup="false" android:largeHeap="true" android:icon="@drawable/test_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
2,數據存儲在 Sqlite 或者輕量級存儲須要對數據進行加密,取出來的時候進行解密。
3,使用 Android 的 AES/DES/DESede 加密算法時,不要使用默認的加密模式ECB,應顯示指定使用 CBC 或 CFB 加密模式。
說明:
加密模式 ECB、CBC、CFB、OFB 等,其中 ECB 的安全性較弱,會使相同的銘文在不一樣的時候產生相同的密文,容易遇到字典攻擊,建議使用 CBC 或 CFB 模式。
1) ECB:Electronic codebook,電子密碼本模式
2) CBC:Cipher-block chaining,密碼分組連接模式
3) CFB:Cipher feedback,密文反饋模式
4) OFB:Output feedback,輸出反饋模式
4,對於不須要使用 File 協議的應用,禁用 File 協議,顯式設置 webView.getSettings().setAllowFileAccess(false),對於須要使用 File 協議的應用,禁止 File 協議調用 JavaScript,顯式設置 webView.getSettings().setJavaScriptEnabled(false)。
5,Android5.0 之後安全性要求較高的應用應該使用 window.setFlag (LayoutParam.FLAG_SECURE) 禁止錄屏。
6,Android WebView 組件加載網頁發生證書認證錯誤時,採用默認的處理方法handler.cancel(),中止加載問題頁面。
說明:
Android WebView 組件加載網頁發生證書認證錯誤時,會調用 WebViewClient 類的 onReceivedSslError 方法,若是該方法實現調用了 handler.proceed()來忽略該證書錯誤,則會受到中間人攻擊的威脅,可能致使隱私泄露.
反例:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JsBridge(mContext), JS_OBJECT);
mWebView.loadUrl("http://www.example.org/tests/addjsif/");
mWebView.setWebViewClient(new WebViewClient() { @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); // 忽略 SSL 證書錯誤 } });
好了,以上就是閱讀《阿里巴巴Android編碼規範》中我的摘錄的一些以爲須要注意的地方,若是感興趣能夠自行查找完整版所有閱讀一下。
本篇到此結束,但願對你有用。