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卻不怎麼變,這看起來一來不協調,二來沒有達到用戶修改系統字體大小的目的,感受這樣的作法有點破壞系統的生態,不推薦這樣作。