• Android开发代码规范总结


    本篇开始总结Android开发中的一些注意事项,提高代码质量(仅供参考):

    1.  Activity间的数据通信,对于数据量比较大的,避免使用 Intent + Parcelable 的方式,可以考虑 EventBus 等替代方案,以免造成TransactionTooLargeException 。

    2.  Activity间通过隐式 Intent 的跳转,在发出 Intent 之前必须通过 resolveActivity 检查,避免找不到合适的调用组件,造成 ActivityNotFoundException 的异常。

    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) {
                try {
                    startActivity(intent);
                } catch (ActivityNotFoundException e) {
                    if (Config.LOGD) {
                        Log.d(LOGTAG, "activity not found for " + mimeType + " over " + Uri.parse(url).
                                getScheme(), e);
                    }
                }
            }
        }

    3.  避免在 Service#onStartCommand()/onBind()方法中执行耗时操作,如果确实有需求,应改用 IntentService 或 采用其他异步机制完成;避免在BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时操作,应该创建IntentService完成,而不应该在BroadcastReceiver内创建子线程去做。查看IntentService的具体使用教程(后补)

    4.  建议不要在 Activity#onDestory() 内执行释放资源的工作,例如一些工作线程的销毁和停止,因为 onDestory() 执行的时机可能比较晚。可根据实际需要,在Activity#onPause()/onStop()中结合isFinishing的判断来执行。

    5.  对于只用于应用内的广播,优先使用 LocalBroadcastManager 来进行注册和发送,LocalBroadcastManager 安全性更好,可以避免广播泄露以及广播被拦截等安全问题,同时相对全局广播,本地广播的更高效

    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    
    @Override
    protected void onResume() {
       super.onResume();
       LocalBroadcastManager.getInstance(context).registerReceiver(receiver, filter);
    }
    @Override
    protected void onPause() {
       super.onPause();
       LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
    }

    6.  当前 Activity 的 onPause 方法执行结束后才会执行下一个 Activity 的 onCreate 方法,所以在 onPause 方法中不适合做耗时较长的工作,这会影响到页面之间的跳转效率。

    7.  Activity 或者 Fragment 中动态注册 BroadcastReceiver 时, registerReceiver()和unregisterReceiver()要成对出现。否则会导致内存泄露,加重 SystemService 负担。

    8.  在需要时刻刷新某一区域的组件时,建议通过以下方式避免引发全局 layout 刷新:

      1) 设置固定的 view 大小的高宽,如倒计时组件

      2) 调用 view 的 layout 方式修改位置,如弹幕组件等;

      3) 通过修改 canvas 位置并且调用 invalidate(int l, int t, int r, int b)等方式限定刷新区域;

      4) 通过设置一个是否允许 requestLayout 的变量,然后重写控件的 requestlayout、onSizeChanged 方法,判断控件的大小没有改变的情况下,当进入requestLayout 的时候,直接返回而不调用
        super 的 requestLayout 方法。
     
    9.  新建线程时,必须通过线程池提供(AsyncTask 或者 ThreadPoolExecutor或者其他形式自定义的线程池),不允许在应用中自行显式创建线程。线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。说明:Executors 返回的线程池对象的弊端如下:
      1) FixedThreadPool 和 SingleThreadPool : 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM;
      2) 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());

    11.  谨慎使用 Android 的多进程,多进程虽然能够降低主进程的内存压力,但会遇到如下问题:
      1) 不能实现完全退出所有 Activity 的功能
      2) 首次进入新启动进程的页面时会有延时的现象(有可能黑屏、白屏几秒,是白屏还是黑屏和新 Activity 的主题有关);
      3) 应用内多进程时,Application 实例化多次,需要考虑各个模块是否都需要在所有进程中初始化;
      4) 多进程间通过 SharedPreferences 共享数据时不稳定。

    12.  使用完毕的图片,应该及时回收,释放宝贵的内存。

    // 使用结束,在 2.3.3 及以下需要调用 recycle()函数,在 2.3.3 以上 GC 会自动管理,除非你明确不需要再用。if (Build.VERSION.SDK_INT <= 10) {
      bitmap.recycle();
    }
    bitmap = null;

    13.  在 Activity.onPause() 或 Activity.onStop() 回调中,关闭当前 activity 正在执行的动画。

    public void onPause(){
       //页面退出,及时清理动画资源
       mImageView.clearAnimation();
    }

    14. 使用 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);

    15. ※ ※ ※  在有强依赖 onAnimationEnd 回调的交互时,如动画播放完毕才能操作页面 , onAnimationEnd 可能会 因各种异常没被回调 (参考:https://stackoverflow.com/questions/5474923/onanimationend-is-not-getting-called-onanimationstart-works-fine),建议加上超时保护 或通过 postDelay 替 代 onAnimationEnd。

    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(); // 当 View Animation 执行结束时,调用 View.clearAnimation()释放相关资源
                }
            }
        }, anim.getDuration());
    v.startAnimation();

     16. 给Fragment传递参数时,不要创建有参构造方法,要通过Arguments传参。因为Activity在恢复Fragment会通过反射查找无参构造函数。

  • 相关阅读:
    Python---列表相关操作
    PyCharm使用小技巧--git上传代码至远程仓库
    Linux下修改文件权限
    Linux运行jmeter
    Jmeter添加负载机
    git使用
    Linux之12——常用统计命令之uniq
    Linux之11——常用统计命令之sort
    Linux之10——dd命令详解
    Linux之8——性能调优之iostat命令详解
  • 原文地址:https://www.cnblogs.com/aimqqroad-13/p/8691307.html
Copyright © 2020-2023  润新知