《阿里巴巴Android编码规范》阅读纪要(二)

版权声明:本文出自汪磊的博客,转载请务必注明出处。

本篇继续上一篇《阿里巴巴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编码规范》中我的摘录的一些以为须要注意的地方,若是感兴趣能够自行查找完整版所有阅读一下。

本篇到此结束,但愿对你有用。

相关文章
相关标签/搜索