Android 開發小提示集合
來自: http://blog.chengyunfeng.com/?p=867
本篇文章記錄了各種 Android 開發過程中可能會用到的小技巧,有些可能你已經知道,有些可能你第一次聽說。使用這些提示可以幫助提高開發效率、避免潛在的問題。
</div>
提示1
AndroidStudio 包含了一個非常方便的圖標生成器。支持各種風格的圖標生成,比如 通知圖標、啟動圖標、tab 圖標等。并且支持 png 和 svg 格式的圖標。該工具位于菜單:[File] >[New] >[Image Asset] 和 [File] >[New] >[Vector Asset]
提示2
想要在 Gradle 中執行單個測試? 下面的命令可以幫助你:
./gradlew testDebug –tests=’*.
提示3
在開發測試階段使用 strict mode 來確保您沒有在主線程中干了不該干的事,比如 訪問 磁盤文件和網絡操作等。
Java
if (BuildConfig.DEBUG) { StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectAll() .penaltyLog() .build()); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectAll() .penaltyLog() .penaltyDeathOnNetwork() .build()); }
if (BuildConfig.DEBUG) { StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectAll() .penaltyLog() .build()); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectAll() .penaltyLog() .penaltyDeathOnNetwork() .build()); }</div>
發布版本中記得關閉該功能, 否則會影響性能。
提示4
在使用 Picasso 圖片庫的時候,可以通過 RequestTransformer 來添加請求圖片 url 的參數。例如添加需要請求圖片的尺寸信息。
提示5
如果在 Android activity manifest 文件中使用了 android:windowSoftInputMode=”adjustResize” 屬性。當軟鍵盤出現的時候,則 ScrollView (或者其他可以滾動的 ViewGroup)會縮小其高度。 但是 如果你在 Activity theme 中使用 android:windowFullscreen=”true” 屬性,則 ScrollView 高度不會改變,應用該屬性強制其高度為 屏幕高度。 同樣 使用 android:fitsSystemWindows=”false” 高度也不會改變。
提示6
如果 Android 系統在更新 Webview 的時候,您的應用如果使用了 Webview 并且正在運行則會導致您的應用崩潰。 http://stackoverflow.com/questions/29575313/namenotfoundexception-webview
提示7
Material Design(紙墨設計)中定義了標準的 padding 和 margin 值,除非您有特殊的要求可以不按照該規范設計UI。 否則你可以通過 https://play.google.com/store/apps/details?id=com.faizmalkani.keylines 應用來檢測你的 UI 是否準守該規范。
提示8
RecyclerView 的 getChildLayoutPosition 返回子元素的位置,如果該元素從 Adapter 中刪除了 但是該元素在 UI 上還存在(比如滑動刪除, 正在做刪除的動畫),則 getChildLayoutPosition 依然會返回正確的 位置信息。
提示9
如果需要空集合對象的時候,請使用 Collections.emptyList() 和 Collections.emptySet()。該函數確保生成一個單例的空集合。
提示10
如果你使用 ZXing 庫的 QRCodeWriter 來生成二維碼。如果生成的圖片比較大則需要很多時間來生成圖片。你可以使用參數 0x0 作為尺寸信息,則 QRCodeWriter 會返回一個 BitMatrix 對象,里面包含了生成該二維碼所需要的最少的像素信息(每個塊為一個像素)。然后你可以把該 BitMatrix 數據寫到 BitmapDrawable 對象上,然后把該 BitmapDrawable 用作 View 的背景。注意:需要調用 drawable 的setFilterBitmap(false) 來避免縮放。
Java
BitMatrix matrix = new QRCodeWriter().encode("content here", BarcodeFormat.QR_CODE, 0, 0); int height = matrix.getHeight(); int width = matrix.getWidth(); Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); for (int x = 0; x < width; x++) { for (int y = 0; y < width; y++) { bmp.setPixel(x, y, matrix.get(x, y) ? Color.BLACK : Color.TRANSPARENT); } } BitmapDrawable qrCodeDrawable = new BitmapDrawable(getResources(), bmp); qrCodeDrawable.setFilterBitmap(false); imgQrCode.setBackground(qrCodeDrawable);
BitMatrixmatrix = new QRCodeWriter().encode("content here", BarcodeFormat.QR_CODE, 0, 0); int height = matrix.getHeight(); int width = matrix.getWidth(); Bitmapbmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); for (int x = 0; x < width; x++) { for (int y = 0; y < width; y++) { bmp.setPixel(x, y, matrix.get(x, y) ? Color.BLACK : Color.TRANSPARENT); } } BitmapDrawableqrCodeDrawable = new BitmapDrawable(getResources(), bmp); qrCodeDrawable.setFilterBitmap(false); imgQrCode.setBackground(qrCodeDrawable);</div>
上面示例中使用了參數 Bitmap.Config.ARGB_4444,這樣生成的圖片背景為透明的。如果你只需要黑白的圖片,則可以使用 Bitmap.Config.RGB_565。另外為了保險起見,還可以使用 BitMatrix matrix = new QRCodeWriter().encode(“content here”, BarcodeFormat.QR_CODE, 10, 10); ,這樣可以預防 ZXing 停止支持 0 0 參數。
提示 11
使用 adb hell 來替代 adb shell 會有意想不到的收獲。(Windows 用戶沒啥收獲 ^_^)
提示 12
TextUtils.concat() 函數的參數為 CharSequence ,并且保留了每個CharSequence 中的 spans 設置。
提示 13
當批量操作數據庫的時候,可以使用 SqliteDatabase 的 beginTransaction() 和 endTransaction() 函數。 記得調用 setTransactionSuccessful() 函數,否則的話,在endTransaction() 執行的時候,所有的操作都會回滾到之前的狀態。
提示 14
Sqlite 數據庫很多操作都有一些限制,這里有詳細的描述:https://www.sqlite.org/limits.html 。請看看這些限制做到心中有數。
提示 15
如果一個 View 不在界面最上面不應該接受點擊事件,則可以通過 setFilterTouchesWhenObscured 函數來做到這點。 這樣可以避免木馬軟件竊取信息: http://developer.android.com/reference/android/view/View.html#setFilterTouchesWhenObscured(boolean)
提示 16
當顯示加載內容ProgressBar 的時候,考慮使用 ContentLoadingProgressBar
/**
* ContentLoadingProgressBar implements a ProgressBar that waits > a minimum time to be
* dismissed before showing. Once visible, the progress bar will > be visible for
* a minimum amount of time to avoid “flashes” in the UI when an > event could take
* a largely variable time to complete (from none, to a user perceivable amount)
*/
</div>
https://developer.android.com/reference/android/support/v4/widget/ContentLoadingProgressBar.html
提示 17
OSX 系統文件名字是不區分大小寫的,但是終端窗口中是區分的。當你把 myClass.java 重命名為 MyClass.java 會有問題的。 需要注意該問題。
提示 18
使用 Picasso 的resize() 功能的時候,如果你把其中的一個參數設置為 0,則 Picasso 會保持該圖片的長寬比來計算該值。
提示 19
View 只有帶有 ID 的時候才能保持其狀態。
提示 20
AppCompatDialog.setStyle(STYLE_NO_TITLE, …) 其實并沒有用,并拋出一個異常。你應該創建一個 Style 并且把該 style 作為 對話框的 構造函數參數。
提示 21
在 Android 6.0+ 系統上通過 照相機應用的 Intent 來獲取照片的時候,需要 Camera 權限才能獲取到返回的圖片數據。
提示 22
ViewPager 的 onPageScrolled 回調函數可以獲取到當前頁面滾動的位置,使用該信息可以修改 tab 的顯示狀態。
提示 23
使用 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 可以在有輸入框的對話框顯示的時候不顯示軟鍵盤。
提示 24
如果你覆蓋了 DialogFragment 的 onCreateDialog 函數而不是 onCreateView 。則 onViewCreated 函數不會被調用。
提示 25
庫項目的 BuildConfig.DEBUG 和 app 的 BuildConfig.DEBUG 不一樣。
提示 26
adb longcat 和 adb logcat -v long 是一樣的。
提示 27
當調用一個服務器API 并顯示一個 dialog fragments 的時候,請注意該操作可能發生在 activity 的狀態已經保存的時候,這樣會拋出異常。解決方式:只在 onResume() 和 onPause() 之間顯示對話框。
提示 28
在 build.gradle 的 defaultConfig 中添加:
archivesBaseName = “halogen-$versionName-$versionCode”
就可以在輸出的 apk 中添加 版本名字和版本代號字段了。
提示 29
想要自動刪除 unaligned .apks 文件則可以使用如下的代碼:
Java
applicationVariants.all { variant -> variant.assemble.doLast { variant.outputs.each { output -> File unaligned = output.packageApplication.outputFile; File aligned = output.outputFile if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) { println "deleting " + unaligned.getName() unaligned.delete() } } } }
applicationVariants.all { variant -> variant.assemble.doLast { variant.outputs.each { output -> Fileunaligned = output.packageApplication.outputFile; Filealigned = output.outputFile if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) { println "deleting " + unaligned.getName() unaligned.delete() } } } }</div>
來源: willowtreeapps
</div>