乱乱记

一个小功能心得

下面的记录比较琐碎,是日常碰到的一些小知识点,什么都有,所有比较乱,不适合对某一类问题的参考,适合对开发点滴的积累。

  • 文件的读取和移除

    • 对指定目录的读和写
    • 对文件的筛选(filter 和是否为隐藏文件和文件夹,是文件夹的话,继续读取文件夹里面的文件)
    • 对文件进行操作时要注意是否需要对文件操作的返回值做判断,以便得到是否文件操作成功;
  • imageView的设置:

    • setBackgroundResource()、setBackgroundDrawable()
    • setImageResource()、setImageDrawable()
    • 两者是有区别的
  • 动画的从无到有:

    是一层一层绘画出来的,要耐心细致的去完成。急不得,往往在动画的先后和实现逻辑上会反复多思量。

  • breakcontinue的区别!!!别乱用啊喂!

    break 会打破整个for循环,所有剩下循环里面的东西全部停止;

    continue会打破本次的for循环,会接着做下一次for循环。

  • 动画在运行时的卡顿问题:

    可能是因为动画开始时布局文件尚未绘制好,导致的丢帧情况(一下子,顿一下,运行或直接接跳过一段时间),这时需要postDelay 一下,尽可能不会发生draw丢帧情况(丢帧是可能会跳过view的部分draw()方法)

    • 动画的默认加速器不是线性的,如需要线性,则直接指定一下加速器
    animator.setInterpolator(new LinearInterpolator())
    
    • 默认的加速器是:AccelerateDecelerateInterpolator(),效果是先加速后减速。
  • 动画的后续处理

    对于设置为scanAnimator.setRepeatCount(ValueAnimator.INFINITE);的动画要格外注意,如果没有及时的销毁它,它会一直start, 造成内存泄漏,最终会crash。

     scanAnimator.setRepeatCount(ValueAnimator.INFINITE);
     ....
     ....
     if(scanAnimator != null) {
         scanAnimator.removeAllListeners();
         scanAnimator.start;
     }
    
  • RecyclerView 的设置问题

    RecyclerView 高度设置为wrap_content,子item有收缩、展开动画,在点击收缩时,可能会出现奇怪的界面刷新方式,原因可能是由于收缩时item已经没有空间位置了,但是需要做动画去完成,没有足够的空间位置,导致动画特别的奇怪,不协调。

  • 接口与回调的实现
    接口很大的用处在与它可以很方便的实现在合适的位置去调用想要处理的代码,这个实现起来很有心得。监听事件是一个很好的接口。

  • flexibleadapter 的实现

    它的HeadCategoryItemsubCategoryItem 是一一对应的。

    adapter.updateDateSet();
    //里面包含着
    adapter.notifyDataSetChanged();
    
    
  • sharedPreference 存储

    • 分情况可能需要考虑夸进程间数据的交互

    • 有些情况下,有些数据不需要存储,

      需要从已知数据中取得它的key的话,这个 (key, value)是不需要存的

  • 要考虑耗时的操作

    • 多线程的并发操作

    • 例如读文件。如果用户的文件量比较大的话,就会有一定的UI线程影响,需要设置一个Thread去处理这个耗时操作。

    • 同时要考虑到在Thread里执行的数据,得到的额数据是否会有并发情况的产生;

      Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略.CopyOnWrite提供了两个容器:

      • CopyOnWriteArrayList
      • CopyOnWriteArraySet
      • ConcurrentHashMap 很相似
- Thread 更新UI数据

    可以使用几种方式去处理,常用的是与`handler`连用,在`handler`里处理的是属于**UI线程**。
    
```
new Thread(new Runnable() {
    @Override
    public void run () {
        ....
        ....
        //一系列的操作
        handler.post(new Runnable {
            @Override
            public void run() {
                //在这里做UI 操作,是回到了UI线程
            }
        });
    }
});
```
  • 对于方法中,返回值为null问题

    注意在以后的编码中,要特别注意这点,尽量不让方法的返回值为null, 尽可能返回,例如:

    public List getScanList() {
        List fileList = new ArrayList<>();
        if(...) {
            //return null;改为
            return fileList;
        }
        ....
        ....
    }
    

    这样可以避免方法的返回值为null时,造成的crash.

    同时对于判断list 里是否含有值:

    list.size == 0;
    //更改为
    list.isEmpty();
    
  • 对于一个新功能的分包问题

    一般来说,现在项目都是按功能分包的,但是具体到下面的每一项,是利用各个功能子模块分包还是依靠文件的分类来分包,就需要各自考量了。

  • 利用注解去限定参数的取值范围

    可以给其他开发者一个更好的说明,编译器也会及时发现传送的错误参数

    @FileUtils.FileDateType
    private int headDateType;
    
    public HeadCategoryItem(@FileUtils.FileDateType int headDateType) {
        this.headDateType = headDateType;
        ...
    }
    
  • 逻辑的实现

    有时候一些比较复杂的逻辑,需要多次反复的去推理,而且,往往,可以进行简单的方法实现(简单的方法不一定是指效率最好的方法,而是最为通俗易懂,最为明了的方法)。

    有时不需要去追寻很高的很快的实现方式,因为往往,这些算法相差不大,而后者代码的可读性会更好,维护起来也会更方便。

  • 在利用ViewHolder时的问题

    ViewHolder经常会与RecyclerView一起连用,但是存在着ViewHolder被复用的情况,有时候界面的刷新会出现问题,就是由于ViewHolder被复用,在上一次某个ViewHolder被设置的值,在这一次的刷新中,没有涉及到它的数据更新!要多注意。

  • Toast的展示

    Toast的展示, 操作为:

    Toast.makeText(Application.getContext(), "toast is showing",
                            Toast.LENGTH_SHORT).show();
                            
    

    第一个参数为context, 以后显示toast最好不以当前contextactivityview, fragment)为context,而是以application的context为context。因为Toast的显示不只显示在当前界面,可能会跨多个界面展示。这样的方式更好一些。

  • Collections.unmodifiableList(list)的使用

    目的是返回一个不可修改的list,主要目的是为里面维护该list的私有性,对外只可读,不可修改,当要去修改时,会抛出java.lang.UnsupportedOperationException异常。

    是重构时一个必要的过程。

    要多思考啊!不要随便对外返回数据!!!

  • 数组的特殊使用,追踪每次变化

    有时候需要一个常量,再每次操作一个方法时可能需要把它进行一些操作,这个常量再某个地方会再次被使用。

    现在有这样一种思路: 利用一个大小为1的数组实现该功能。

    int[] totalTemp = new int[1];
    updateFirstCard(totalTemp);
    updateSecondCard(totalTemp);
    updateThirdCard(totalTemp);
    
    int total = totalTemp[0];
    //total里为每次更新后的值
    
    ....
    private void updateFirstCard(int[] totalTemp) {
        ...
        totalTemp[0] += 100;
        ...
    }
    ...
    

    其原理是引用,数组的引用在传递参数的过程中,它的指向一直没有变化,所发生的操作均在指向上的操作,所以最后我们拿到的值(这个指向所存储的值)是每次更新后的正确的值。

    很容易理解,但经常会想不到这种比较巧妙的方式。

你可能感兴趣的:(乱乱记)