# 第三十二周ARTS总结

# Algorithm

1ms | 99.69% Run time
34.1MB | 100.00% Memory

public String countAndSay(int n) {
    if (n > 1) {
        // 获取n-1返回的值
        String lastAns = countAndSay(n - 1);

        StringBuilder ans = new StringBuilder();

        // 初始化两个局部变量
        char num = lastAns.charAt(0);
        int count = 0;

        // 遍历字符串,得到需要的字符串
        for (int i = 0; i < lastAns.length(); i++) {
            if (lastAns.charAt(i) != num) {
                if (count > 0) {
                    ans.append((char) ('0' + count)).append(num);
                }

                num = lastAns.charAt(i);
                count = 1;
            } else {
                num = lastAns.charAt(i);
                count++;
            }

            // 处理结束了的情况
            if (i == lastAns.length() - 1) {
                ans.append((char) ('0' + count)).append(num);
            }
        }

        return ans.toString();
    } else {
        return "1";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# Review

# Tip

  • SnapHelper:用于辅助RecyclerView在滚动结束时将item对齐到某个位置。特别是列表横向滑动时,很多时候不会让列表滑到任意位置,而是会有一定的规则限制。
    • LinearSnapHelper
    • PagerSnapHelper
  • ViewFlipperViewAnimator的子类,而ViewAnimator又是继承自FrameLayout,而FrameLayout就是平时基本上只显示一个子视图的布局,由于FrameLayout下不好确定子视图的位置,所以很多情况下子视图之前存在相互遮挡,这样就造成了很多时候我们基本上只要求FrameLayout显示一个子视图,然后通过某些控制来实现切换。正好,ViewFlipper帮我们实现了这个工作,我们需要做的就是,选择恰当的时机调用其恰当的方法即可。
  • 注解:注解使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。注解可以用来生成描述符文件。甚至是新的类定义,并且有助于减轻编写样板代码的负担。
    • 元注解
      • @Target:配置该注解可以用在什么地方
      • @Retention:配置该注解在什么级别下被保存
      • @Documented:将注解包含在JavaDoc
      • @Inherited:允许子类继承父类红的注解
      • @Repeatable:允许同一个地方多次使用同一种注解类型(jdk1.8后加入)
    • 注解的使用
      1. 定义注解
      2. 使用注解
      3. 利用反射获取注解信息并做处理
  • APT工具:APTjavac中提供的一种编译时扫描和处理注解的工具,它会对源代码文件进行检查,并找出其中的注解,然后根据用户自定义的注解处理方法进行额外的处理。APT工具不仅能解析注解,还能根据注解生成其他的源文件,最终将生成的新的源文件与原来的源文件共同编译(注意:APT并不能对源文件进行修改操作,只能生成新的文件,例如在已有的类中添加方法)
    • APT项目构建三部分:
      • 注解处理器库(包含我们的注解处理器)
      • 注解声明库(用于存储声明的注解)
      • 实际使用APTAndroid/Java项目
    • 使用步骤:
      1. 注解处理器的声明
      2. 注册注解处理器
      3. 注解处理器的扫描
      4. 文件生成(利用JavaPoet
  • Dagger核心知识点
    • Inject:标注目标类的依赖和依赖的构造函数
    • Component:它是一个桥梁,一端是目标类,另一端是目标类所依赖类的实例,它也是注入器(Injector)负责把目标类所依赖类的实例注入到目标类中,同时它也管理Module
    • ModuleProvides:是为解决第三方类库而生的,Module是一个简单工厂模式,Module可以包含创建类实例的方法,这些方法用Provides来标注
    • 总的来说:Component相当于注射器,Module是注射液,Inject是被注射体中的目标
  • Dagger的使用:
    • 简单使用
      1. @Inject标注于构造方法,告诉Dagger2可以实例化这个类
      2. 使用注解@Component定义注射器,其中类名、方法名随意,方法参数为被注射类
      3. 编译项目,自动生成DaggerComponent类,类名为Dagge+我们定义的Component的名字
      4. 在被注射类中调用DaggerXXX.create().injectTo(this);,即打针
      5. 在被注射类中直接使用注射液
    • @Module的使用
      1. @Module标注Module类,用@Provides标注方法的返回值,即我们需要@Inject的类型
      2. @Component(modules = AModule.class)指定注射器注射液
      3. 接下来与简单使用的步骤3~5一致
    • 通过Module传参(主要用于Module类的构造方法带参且被使用的情况)
      1. @Module标注Module类,用@Provides标注方法的返回值,即我们需要@Inject的类型。其中方法的返回值可能与Module构造方法的参数有关
      2. @Component(modules = AModule.class)指定注射器注射液
      3. 编译项目,自动生成DaggerComponent类,类名为Dagge+我们定义的Component的名字
      4. 在被注射类中调用DaggerXXX.builder().aModule(new AModule("xxx")).build().injectTo(this);,即打针注:此时的Module需要手动传入
      5. 在被注射类中直接使用注射液
    • 自定义Builder(上述使用的BuilderAPT自动生成的,现在来自定义Builder
      1. 与上述的1~2步骤一致
      2. 自定义一个接口类,并用@Component.Builder标注。其中有两个方法:返回值为本身的方法+返回值为XXXComponent的方法
        例:
        @Component(modules = AModule.class)
         public interface TestComponent {
         
             void injectTo(MainActivity mainActivity);
         
             @Component.Builder
             interface Builder {
                 Builder aModule(AModule aModule);
         
                 TestComponent build();
             }
         }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
      3. 接下来与上述的3~5一致
    • 使用@BindsInstance(为了精简BuilderaModule方法)
      1. 改造Module,将构造方法中的参数变为方法的形参
      2. 修改Component,将返回值为Builder的方法参数作修改
      3. 打针的时候输入的参数作精简 注:目的是为了在打针的时候不用手动new一个对象,而是直接传入对象所需要的参数值
    • 使用dependencies实现Component依赖Component
      1. Module类正常,不改变
      2. 父注射器要把注入类返回
      3. 子注射器需要依赖父注射器,通过dependencies
      4. 子注射器打针的时候需要父注射器的实例
    • 使用@subComponent实现Component依赖Component
    • 使用@Subcomponent.Builder实现Component依赖Component
  • Dagger2中常见的注解:
    • @Named:用于标识不同的初始化路径
    • @Qualifier
    • @Singleton:作用域单例(与该DaggerComponent的生命周期一致)
    • @Scope
    • Provider:一种工厂模式的容器
    • Lazy:懒加载容器,只有调用get()的时候才会生成实例,并且实例只有一份

# Share

暂无内容

更新时间: 10/20/2022, 7:04:01 AM