本篇文章记录了各种 Android 开发过程中可能会用到的小技巧,有些可能你已经知道,有些可能你第一次听说。使用这些提示可以帮助提高开发效率、避免潜在的问题。
AndroidStudio 包含了一个非常方便的图标生成器。支持各种风格的图标生成,比如 通知图标、启动图标、tab 图标等。并且支持 png 和 svg 格式的图标。该工具位于菜单:[File] >[New] >[Image Asset] 和 [File] >[New] >[Vector Asset]
想要在 Gradle 中执行单个测试? 下面的命令可以帮助你:
./gradlew testDebug –tests=’*.
在开发测试阶段使用 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()); }
发布版本中记得关闭该功能, 否则会影响性能。
在使用 Picasso 图片库的时候,可以通过 RequestTransformer 来添加请求图片 url 的参数。例如添加需要请求图片的尺寸信息。
如果在 Android activity manifest 文件中使用了 android:windowSoftInputMode=”adjustResize” 属性。当软键盘出现的时候,则 ScrollView (或者其他可以滚动的 ViewGroup)会缩小其高度。 但是 如果你在 Activity theme 中使用 android:windowFullscreen=”true” 属性,则 ScrollView 高度不会改变,应用该属性强制其高度为 屏幕高度。 同样 使用 android:fitsSystemWindows=”false” 高度也不会改变。
如果 Android 系统在更新 Webview 的时候,您的应用如果使用了 Webview 并且正在运行则会导致您的应用崩溃。 http://stackoverflow.com/questions/29575313/namenotfoundexception-webview
Material Design(纸墨设计)中定义了标准的 padding 和 margin 值,除非您有特殊的要求可以不按照该规范设计UI。 否则你可以通过 https://play.google.com/store/apps/details?id=com.faizmalkani.keylines 应用来检测你的 UI 是否准守该规范。
RecyclerView 的 getChildLayoutPosition 返回子元素的位置,如果该元素从 Adapter 中删除了 但是该元素在 UI 上还存在(比如滑动删除, 正在做删除的动画),则 getChildLayoutPosition 依然会返回正确的 位置信息。
如果需要空集合对象的时候,请使用 Collections.emptyList() 和 Collections.emptySet()。该函数确保生成一个单例的空集合。
如果你使用 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);
上面示例中使用了参数 Bitmap.Config.ARGB_4444,这样生成的图片背景为透明的。如果你只需要黑白的图片,则可以使用 Bitmap.Config.RGB_565。另外为了保险起见,还可以使用 BitMatrix matrix = new QRCodeWriter().encode(“content here”, BarcodeFormat.QR_CODE, 10, 10); ,这样可以预防 ZXing 停止支持 0 0 参数。
使用 adb hell 来替代 adb shell 会有意想不到的收获。(Windows 用户没啥收获 ^_^)
TextUtils.concat() 函数的参数为 CharSequence ,并且保留了每个CharSequence 中的 spans 设置。
当批量操作数据库的时候,可以使用 SqliteDatabase 的 beginTransaction() 和 endTransaction() 函数。 记得调用 setTransactionSuccessful() 函数,否则的话,在endTransaction() 执行的时候,所有的操作都会回滚到之前的状态。
Sqlite 数据库很多操作都有一些限制,这里有详细的描述:https://www.sqlite.org/limits.html 。请看看这些限制做到心中有数。
如果一个 View 不在界面最上面不应该接受点击事件,则可以通过 setFilterTouchesWhenObscured 函数来做到这点。 这样可以避免木马软件窃取信息: http://developer.android.com/reference/android/view/View.html#setFilterTouchesWhenObscured(boolean)
当显示加载内容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)
*/
https://developer.android.com/reference/android/support/v4/widget/ContentLoadingProgressBar.html
OSX 系统文件名字是不区分大小写的,但是终端窗口中是区分的。当你把 myClass.java 重命名为 MyClass.java 会有问题的。 需要注意该问题。
使用 Picasso 的resize() 功能的时候,如果你把其中的一个参数设置为 0,则 Picasso 会保持该图片的长宽比来计算该值。
View 只有带有 ID 的时候才能保持其状态。
AppCompatDialog.setStyle(STYLE_NO_TITLE, …) 其实并没有用,并抛出一个异常。你应该创建一个 Style 并且把该 style 作为 对话框的 构造函数参数。
在 Android 6.0+ 系统上通过 照相机应用的 Intent 来获取照片的时候,需要 Camera 权限才能获取到返回的图片数据。
ViewPager 的 onPageScrolled 回调函数可以获取到当前页面滚动的位置,使用该信息可以修改 tab 的显示状态。
使用 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 可以在有输入框的对话框显示的时候不显示软键盘。
如果你覆盖了 DialogFragment 的 onCreateDialog 函数而不是 onCreateView 。则 onViewCreated 函数不会被调用。
库项目的 BuildConfig.DEBUG 和 app 的 BuildConfig.DEBUG 不一样。
adb longcat 和 adb logcat -v long 是一样的。
当调用一个服务器API 并显示一个 dialog fragments 的时候,请注意该操作可能发生在 activity 的状态已经保存的时候,这样会抛出异常。解决方式:只在 onResume() 和 onPause() 之间显示对话框。
在 build.gradle 的 defaultConfig 中添加:
archivesBaseName = “halogen-$versionName-$versionCode”
就可以在输出的 apk 中添加 版本名字和版本代号字段了。
想要自动删除 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() } } } }
来源: willowtreeapps