2018春节余味还没有消,阿里巴巴为移动开发者们准备了一份迟到的新年礼物——《阿里巴巴Android开发手册》1.0.1版本。android
在此写下个人阅读笔记,记录下本身平时没有注意的一些问题,规范本身。数据库
public void viewUrl(String url, String mimeType) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), mimeType);
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ ONLY) != null) {
startActivity(intent);
} else {
// 找不到指定的 Activity
}
}
复制代码
说明:安全
因为该方法是在主线程执行,若是执行耗时操做会致使 UI 不流畅。可使用IntentService 、 创 建 HandlerThread 或 者 调 用 Context#registerReceiver (BroadcastReceiver, IntentFilter, String, Handler)方法等方式,在其余 Wroker 线程执行 onReceive 方法。BroadcastReceiver#onReceive()方法耗时超过 10 秒钟,可能会被系统杀死。bash
说明:app
Activity 可能由于各类缘由被销毁,Android 支持页面被销毁前经过Activity#onSaveInstanceState() 保 存 自 己 的 状 态 。 但 如 果FragmentTransaction.commit()发生在 Activity 状态保存以后,就会致使 Activity 重 建、恢复状态时没法还原页面状态,从而可能出错。为了不给用户形成很差的体验,系统会抛出 IllegalStateExceptionStateLoss 异常。推荐的作法是在 Activity 的onPostResume() 或 onResumeFragments() ( 对 FragmentActivity ) 里 执 行 FragmentTransaction.commit(),若有必要也可在 onCreate()里执行。不要随意改用FragmentTransaction.commitAllowingStateLoss() 或 者 直 接 使 用 try-catch 避 免 crash,这不是问题的根本解决之道,当且仅当你确认 Activity 重建、恢复状态时,本次 commit 丢失不会形成影响时才可这么作。ide
说明:工具
对于使用 Context#sendBroadcast()等方法发送全局广播的代码进行提示。若是该广播仅用于应用内,则可使用 LocalBroadcastManager 来避免广播泄漏以及广播被拦截等安全问题,同时相对全局广播本地广播的更高效。布局
说明:post
之因此文本大小也推荐使用 dp 而非 sp,由于 sp 是 Android 早期推荐使用的,但其 实 sp 不只和 dp 同样受屏幕密度的影响,还受到系统设置里字体大小的影响,因此使用 dp 对于应用开发会更加保证 UI 的一致性和还原度。字体
说明:
Executors 返回的线程池对象的弊端以下:
FixedThreadPool 和 SingleThreadPool : 允 许 的 请 求 队 列 长 度 为Integer.MAX_VALUE,可能会堆积大量的请求,从而致使 OOM;
CachedThreadPool 和 ScheduledThreadPool : 允 许 的 创 建 线 程 数 量 为Integer.MAX_VALUE,可能会建立大量的线程,从而致使 OOM。
正例:
int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
int KEEP_ALIVE_TIME = 1;
TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<Runnable>();
ExecutorService executorService = new ThreadPoolExecutor(NUMBER_OF_CORES, NUMBER_OF_CORES*2, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT,
taskQueue, new BackgroundThreadFactory(), new DefaultRejectedExecutionHandler());
复制代码
反例:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
复制代码
说明:
Android 应用提供内部和外部存储,分别用于存放应用自身数据以及应用产生的用 户数据。能够经过相关 API 接口获取对应的目录,进行文件操做。
android.os.Environment#getExternalStorageDirectory()
android.os.Environment#getExternalStoragePublicDirectory()
android.content.Context#getFilesDir()
android.content.Context#getCacheDir
正例:
public File getDir(String alName) {
File file = new File(Environment.getExternalStoragePublicDirectory(Environment. DIRECTORY_PICTURES), alName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
复制代码
反例:
public File getDir(String alName) {
// 任什么时候候都不要硬编码文件路径,这不只存在安全隐患,也让 app 更容易出现适配问题
File file = new File("/mnt/sdcard/Download/Album", alName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
复制代码
正例:
// 读/写检查
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
// 只读检查
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
复制代码
???这是个什么梗,都没说清楚???
正例:
// 使用一个可替换参数
String mSelectionClause = "var = ?"; String[] selectionArgs = {""}; selectionArgs[0] = mUserInput;
复制代码
反例:
// 拼接用户输入内容和列名
String mSelectionClause = "var = " + mUserInput;
复制代码
正例:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
// 首先经过 inJustDecodeBounds=true 得到图片的尺寸
final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// 而后根据图片分辨率以及咱们实际须要展现的大小,计算压缩率
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 设置压缩率,并解码
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
复制代码
正例:
public class MyActivity extends Activity {
ImageView mImageView;
Animation mAnimation;
Button mBtn;
@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);
}
};
}
@Override
public void onPause() {
//页面退出,及时清理动画资源
mImageView.clearAnimation();
}
}
复制代码
说明:
android.graphics.Bitmap.Config 类中关于图片颜色的存储方式定义:
ALPHA_8 表明 8 位 Alpha 位图;
ARGB_4444 表明 16 位 ARGB 位图;
ARGB_8888 表明 32 位 ARGB 位图;
RGB_565 表明 8 位 RGB 位图。
位图位数越高,存储的颜色信息越多,图像也就越逼真。大多数场景使用的是ARGB_8888 和 RGB_565,RGB_565 可以在保证图片质量的状况下大大减小内存的开销,是解决 OOM 的一种方法。
可是必定要注意 RGB_565 是没有透明度的,若是图片自己须要保留透明度,那么就不能使用 RGB_565。
正例:
Config config = drawableSave.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8565 : Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
复制代码
反例:
Bitmap newb = Bitmap.createBitmap(width, height, Config.ARGB_8888);
复制代码
正例:
View v = findViewById(R.id.xxxViewID);
final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
new Handler().postDelayed(new Runnable() {
public void run() {
if (v != null) {
v.clearAnimation();
}
}
}, anim.getDuration());
v.startAnimation(anim);
复制代码
正例:
View v = findViewById(R.id.xxxViewID);
final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
anim.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationEnd(Animation arg0) {
//判断一下资源是否被释放了
if (v != null) {
v.clearAnimation();
}
});
v.startAnimation(anim);
复制代码
说真的,这手册总结得挺好的,虽然内容少了点,可是才1.0.1版本,还会继续修改完善的。
我以为上面的第8点写得不太合理:
8.【推荐】文本大小使用单位 dp,View 大小使用单位 dp。对于 TextView,若是在文 字大小肯定的状况下推荐使用 wrap_content 布局避免出现文字显示不全的适配问 题。
说明:
之因此文本大小也推荐使用 dp 而非 sp,由于 sp 是 Android 早期推荐使用的,但其 实 sp 不只和 dp 同样受屏幕密度的影响,还受到系统设置里字体大小的影响,因此使用 dp 对于应用开发会更加保证 UI 的一致性和还原度。
我以为:若是用户设置了系统字体大小,那么确定是但愿系统总体字体变大或变小,而你的APP却不怎么变,这看起来一来不协调,二来没有达到用户修改系统字体大小的目的,感受这样的作法有点破坏系统的生态,不推荐这样作。