ART世界探险(6) - 流程控制指令

ART世界探险(6) - 流程控制指令

分支结构

Java分支结构

我们先来个最简单的,比较大小吧。

    public static long bigger(long a, long b){
        if(a>=b){
            return a;
        }else{
            return b;
        }
    }

    public static int less(int a,int b){
        if(a<=b){
            return a;
        }else{
            return b;
        }
    }

看看Java字节码是个什么样子:

  public static long bigger(long, long);
    Code:
       0: lload_0
       1: lload_2
       2: lcmp
       3: iflt          8
       6: lload_0
       7: lreturn
       8: lload_2
       9: lreturn

  public static int less(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: if_icmpgt     7
       5: iload_0
       6: ireturn
       7: iload_1
       8: ireturn

lcmp是两个长整型做比较,结果影响标志位。然后iflt判断是否是小于(lt=less than),如果是则跳到8 ,不是则继续往下走。

普通整型的判断和比较在同一条指令里,if_icmpgt是判大于(gt=greater than),如果大于则跳转到7。

ARM的分支结构

对于这种根据不同情况选择不同值的语句,ARM在设计时专门有一条强大的csel指令,专门做这个事情。
先用cmp指令比较两个值,然后设置条件,ge是大于或等于,le是小于或等于。如果条件满足,则x0就是x0,否则x0取x1的值。

000000000000079c <_Z6biggerll>:
 79c:   eb01001f    cmp x0, x1
 7a0:   9a81a000    csel    x0, x0, x1, ge
 7a4:   d65f03c0    ret

00000000000007a8 <_Z4lessii>:
 7a8:   6b01001f    cmp w0, w1
 7ac:   1a81d000    csel    w0, w0, w1, le
 7b0:   d65f03c0    ret

Thumb2指令的分支结构

csel这样的指令需要32位的长度才放得下. Thumb2本着能省则省的原则,改用16位的条件mov指令来实现,可以节省2个字节指令空间。

0000101c <_Z6biggerll>:
    101c:   4288        cmp r0, r1
    101e:   bfb8        it  lt
    1020:   4608        movlt   r0, r1
    1022:   4770        bx  lr

00001024 <_Z4lessii>:
    1024:   4288        cmp r0, r1
    1026:   bfa8        it  ge
    1028:   4608        movge   r0, r1
    102a:   4770        bx  lr

Thumb指令的分支结构

Thumb指令没有带条件的mov操作,更不可能有csel这样复杂的指令了。那也没问题,返璞归真,我们直接跳转就是了呗〜
bge.n,是说大于或等于,也就是不小于的时候直接跳到12aa,就是bx lr返回这条指令上去。

adds r0, r1, #0其实也可以翻译成movs r0,r1。前面我们讲过,movs r0,r1其实是adds r0, r1, #0的别名。本质上是一回事。

000012a4 <_Z6biggerll>:
    12a4:   4288        cmp r0, r1
    12a6:   da00        bge.n   12aa <_Z6biggerll+0x6>
    12a8:   1c08        adds    r0, r1, #0
    12aa:   4770        bx  lr

000012ac <_Z4lessii>:
    12ac:   4288        cmp r0, r1
    12ae:   dd00        ble.n   12b2 <_Z4lessii+0x6>
    12b0:   1c08        adds    r0, r1, #0
    12b2:   4770        bx  lr

x86_64的分支结构

x86_64中也是有带有条件的赋值指令的。

0000000000000740 <_Z6biggerll>:
 740:   48 39 f7                cmp    %rsi,%rdi
 743:   48 89 f0                mov    %rsi,%rax
 746:   48 0f 4d c7             cmovge %rdi,%rax
 74a:   c3                      retq   
 74b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

0000000000000750 <_Z4lessii>:
 750:   39 f7                   cmp    %esi,%edi
 752:   89 f0                   mov    %esi,%eax
 754:   0f 4e c7                cmovle %edi,%eax
 757:   c3                      retq   
 758:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
 75f:   00 

x86的分支结构

cmov在x86上也是有的。

00000630 <_Z6biggerll>:
 630:   8b 44 24 04             mov    0x4(%esp),%eax
 634:   8b 54 24 08             mov    0x8(%esp),%edx
 638:   39 d0                   cmp    %edx,%eax
 63a:   0f 4c c2                cmovl  %edx,%eax
 63d:   c3                      ret    
 63e:   66 90                   xchg   %ax,%ax

00000640 <_Z4lessii>:
 640:   8b 44 24 04             mov    0x4(%esp),%eax
 644:   8b 54 24 08             mov    0x8(%esp),%edx
 648:   39 d0                   cmp    %edx,%eax
 64a:   0f 4f c2                cmovg  %edx,%eax
 64d:   c3                      ret    
 64e:   66 90                   xchg   %ax,%ax

mips64的分支结构

感觉上罗嗦了一点,但是本质上跟csel是一样的。

0000000000000c00 <_Z6biggerll>:
 c00:   0085182a    slt v1,a0,a1
 c04:   00832035    seleqz  a0,a0,v1
 c08:   00a31037    selnez  v0,a1,v1
 c0c:   03e00009    jr  ra
 c10:   00821025    or  v0,a0,v0
 c14:   00000000    nop

0000000000000c18 <_Z4lessii>:
 c18:   00a4102a    slt v0,a1,a0
 c1c:   00a22837    selnez  a1,a1,v0
 c20:   00822035    seleqz  a0,a0,v0
 c24:   03e00009    jr  ra
 c28:   00a41025    or  v0,a1,a0
 c2c:   00000000    nop

mips的分支结构:

比起上面64位的,是不是感觉更加清爽呢?

00000710 <_Z6biggerll>:
 710:   0085102a    slt v0,a0,a1
 714:   0082280a    movz    a1,a0,v0
 718:   03e00008    jr  ra
 71c:   00a01021    move    v0,a1

00000720 <_Z4lessii>:
 720:   00a4102a    slt v0,a1,a0
 724:   0082280a    movz    a1,a0,v0
 728:   03e00008    jr  ra
 72c:   00a01021    move    v0,a1

循环结构

我们写一个while循环,一个do while循环和一个for循环来测试一下,其实本质上差不多是一回事情:

    public static long testWhile(int value){
        int i=0;
        long sum = 0;
        while(i<=value){
            sum += i;
            i++;
        }
        return sum;
    }

    public static long testDoWhile(int value){
        long sum = 0;
        int i=0;
        do{
            sum += i;
            i++;
        }while(i<value);
        return sum;
    }

    public static long testFor(int value){
        long sum = 0;
        for(int i=0;i<=value;i++){
            sum += i;
        }
        return sum;
    }

Java字节码的循环结构

我们先来解释其中第一个吧。这其中唯一遇到的新指令是无条件跳转的goto指令。
其中第6标号的if_icmpgt我们在分支中学过了。

  public static long testWhile(int);
    Code:
       0: iconst_0
       1: istore_1
       2: lconst_0
       3: lstore_2
       4: iload_1
       5: iload_0
       6: if_icmpgt     20
       9: lload_2
      10: iload_1
      11: i2l
      12: ladd
      13: lstore_2
      14: iinc          1, 1
      17: goto          4
      20: lload_2
      21: lreturn

后面两个与上面的非常类似。只是指令顺序上稍有不同而己。

  public static long testDoWhile(int);
    Code:
       0: lconst_0
       1: lstore_1
       2: iconst_0
       3: istore_3
       4: lload_1
       5: iload_3
       6: i2l
       7: ladd
       8: lstore_1
       9: iinc          3, 1
      12: iload_3
      13: iload_0
      14: if_icmplt     4
      17: lload_1
      18: lreturn

  public static long testFor(int);
    Code:
       0: lconst_0
       1: lstore_1
       2: iconst_0
       3: istore_3
       4: iload_3
       5: iload_0
       6: if_icmpgt     20
       9: lload_1
      10: iload_3
      11: i2l
      12: ladd
      13: lstore_1
      14: iinc          3, 1
      17: goto          4
      20: lload_1
      21: lreturn

Thumb的循环结构

我们下面来看看16位的Thumb指令是如何实现循环的。
value参数传进来在r0。将r2,r3清0, r2与参数传进来的r0比较,如果0已经比r0大了,循环结束,将结果r3赋给r0,返回。
如果0比r0小,则继续循环,r3结果等于r3值加上r2值,r2值随后加1。然后无条件回12b8那条比较语句,再判断r2是不是大于r0,如此循环。

000012b4 <_Z9testWhilei>:
    12b4:   2300        movs    r3, #0
    12b6:   1c1a        adds    r2, r3, #0
    12b8:   4282        cmp r2, r0
    12ba:   dc02        bgt.n   12c2 <_Z9testWhilei+0xe>
    12bc:   189b        adds    r3, r3, r2
    12be:   3201        adds    r2, #1
    12c0:   e7fa        b.n 12b8 <_Z9testWhilei+0x4>
    12c2:   1c18        adds    r0, r3, #0
    12c4:   4770        bx  lr

后面两个也是语句位置变了变,本质是一样的。

000012c6 <_Z11testDoWhilei>:
    12c6:   2300        movs    r3, #0
    12c8:   1c1a        adds    r2, r3, #0
    12ca:   18d2        adds    r2, r2, r3
    12cc:   3301        adds    r3, #1
    12ce:   4283        cmp r3, r0
    12d0:   dbfb        blt.n   12ca <_Z11testDoWhilei+0x4>
    12d2:   1c10        adds    r0, r2, #0
    12d4:   4770        bx  lr

000012d6 <_Z7testFori>:
    12d6:   2300        movs    r3, #0
    12d8:   1c1a        adds    r2, r3, #0
    12da:   4283        cmp r3, r0
    12dc:   dc02        bgt.n   12e4 <_Z7testFori+0xe>
    12de:   18d2        adds    r2, r2, r3
    12e0:   3301        adds    r3, #1
    12e2:   e7fa        b.n 12da <_Z7testFori+0x4>
    12e4:   1c10        adds    r0, r2, #0
    12e6:   4770        bx  lr

Thumb2的循环结构

v7a的循环结构

我们只看一个吧,除了地址不同,与前面的Thumb指令完全相同,所以略过不讲了。

0000102c <_Z9testWhilei>:
    102c:   2300        movs    r3, #0
    102e:   461a        mov r2, r3
    1030:   4282        cmp r2, r0
    1032:   dc02        bgt.n   103a <_Z9testWhilei+0xe>
    1034:   4413        add r3, r2
    1036:   3201        adds    r2, #1
    1038:   e7fa        b.n 1030 <_Z9testWhilei+0x4>
    103a:   4618        mov r0, r3
    103c:   4770        bx  lr

mips的循环结构

我们再看下mips的三个循环结构,也跟上面所讲的差不多。

00000730 <_Z9testWhilei>:
 730:   04800009    bltz    a0,758 <_Z9testWhilei+0x28>
 734:   24840001    addiu   a0,a0,1
 738:   00001021    move    v0,zero
 73c:   00001821    move    v1,zero
 740:   00431021    addu    v0,v0,v1
 744:   24630001    addiu   v1,v1,1
 748:   1464fffe    bne v1,a0,744 <_Z9testWhilei+0x14>
 74c:   00431021    addu    v0,v0,v1
 750:   03e00008    jr  ra
 754:   00431023    subu    v0,v0,v1
 758:   03e00008    jr  ra
 75c:   00001021    move    v0,zero

00000760 <_Z11testDoWhilei>:
 760:   00001821    move    v1,zero
 764:   00001021    move    v0,zero
 768:   00431021    addu    v0,v0,v1
 76c:   24630001    addiu   v1,v1,1
 770:   0064282a    slt a1,v1,a0
 774:   14a0fffd    bnez    a1,76c <_Z11testDoWhilei+0xc>
 778:   00431021    addu    v0,v0,v1
 77c:   03e00008    jr  ra
 780:   00431023    subu    v0,v0,v1

00000784 <_Z7testFori>:
 784:   04800009    bltz    a0,7ac <_Z7testFori+0x28>
 788:   24840001    addiu   a0,a0,1
 78c:   00001821    move    v1,zero
 790:   00001021    move    v0,zero
 794:   00431021    addu    v0,v0,v1
 798:   24630001    addiu   v1,v1,1
 79c:   1464fffe    bne v1,a0,798 <_Z7testFori+0x14>
 7a0:   00431021    addu    v0,v0,v1
 7a4:   03e00008    jr  ra
 7a8:   00431023    subu    v0,v0,v1
 7ac:   03e00008    jr  ra
 7b0:   00001021    move    v0,zero

mips64的循环结构

64位的除了加减法换成支持64位的了,其它没有变化。

0000000000000c30 <_Z9testWhilei>:
 c30:   0480000a    bltz    a0,c5c <_Z9testWhilei+0x2c>
 c34:   64840001    daddiu  a0,a0,1
 c38:   0000182d    move    v1,zero
 c3c:   0000102d    move    v0,zero
 c40:   0043102d    daddu   v0,v0,v1
 c44:   00000000    nop
 c48:   64630001    daddiu  v1,v1,1
 c4c:   1464fffe    bne v1,a0,c48 <_Z9testWhilei+0x18>
 c50:   0043102d    daddu   v0,v0,v1
 c54:   03e00009    jr  ra
 c58:   0043102f    dsubu   v0,v0,v1
 c5c:   03e00009    jr  ra
 c60:   0000102d    move    v0,zero
 c64:   00000000    nop

0000000000000c68 <_Z11testDoWhilei>:
 c68:   0000182d    move    v1,zero
 c6c:   0000102d    move    v0,zero
 c70:   0043102d    daddu   v0,v0,v1
 c74:   64630001    daddiu  v1,v1,1
 c78:   00032800    sll a1,v1,0x0
 c7c:   5ca4fffc    bltc    a1,a0,c70 <_Z11testDoWhilei+0x8>
 c80:   00000000    nop
 c84:   d81f0000    jrc ra

0000000000000c88 <_Z7testFori>:
 c88:   0480000a    bltz    a0,cb4 <_Z7testFori+0x2c>
 c8c:   64840001    daddiu  a0,a0,1
 c90:   0000182d    move    v1,zero
 c94:   0000102d    move    v0,zero
 c98:   0043102d    daddu   v0,v0,v1
 c9c:   00000000    nop
 ca0:   64630001    daddiu  v1,v1,1
 ca4:   1464fffe    bne v1,a0,ca0 <_Z7testFori+0x18>
 ca8:   0043102d    daddu   v0,v0,v1
 cac:   03e00009    jr  ra
 cb0:   0043102f    dsubu   v0,v0,v1
 cb4:   03e00009    jr  ra
 cb8:   0000102d    move    v0,zero
 cbc:   00000000    nop

arm v8a的循环结构

下面我们看第一个while循环在v8a上的实现:
竟然动用了强大的NEON指令!

00000000000007c0 <_Z9testWhilei>:
 7c0:   2a0003e3    mov w3, w0
 7c4:   37f80643    tbnz    w3, #31, 88c <_Z9testWhilei+0xcc>
 7c8:   51000c60    sub w0, w3, #0x3
 7cc:   7100147f    cmp w3, #0x5
 7d0:   53027c00    lsr w0, w0, #2
 7d4:   11000464    add w4, w3, #0x1
 7d8:   11000400    add w0, w0, #0x1
 7dc:   531e7402    lsl w2, w0, #2
 7e0:   5400050d    b.le    880 <_Z9testWhilei+0xc0>
 7e4:   100005e5    adr x5, 8a0 <_Z9testWhilei+0xe0>
 7e8:   4f000484    movi    v4.4s, #0x4
 7ec:   4f000400    movi    v0.4s, #0x0
 7f0:   52800001    mov w1, #0x0                    // #0
 7f4:   3dc000a1    ldr q1, [x5]
 7f8:   0f20a422    sxtl    v2.2d, v1.2s
 7fc:   11000421    add w1, w1, #0x1
 800:   4f20a423    sxtl2   v3.2d, v1.4s
 804:   6b01001f    cmp w0, w1
 808:   4ea48421    add v1.4s, v1.4s, v4.4s
 80c:   4ee08440    add v0.2d, v2.2d, v0.2d
 810:   4ee08460    add v0.2d, v3.2d, v0.2d
 814:   54ffff28    b.hi    7f8 <_Z9testWhilei+0x38>
 818:   5ef1b800    addp    d0, v0.2d
 81c:   6b02009f    cmp w4, w2
 820:   4e083c00    mov x0, v0.d[0]
 824:   540002c0    b.eq    87c <_Z9testWhilei+0xbc>
 828:   11000444    add w4, w2, #0x1
 82c:   8b22c000    add x0, x0, w2, sxtw
 830:   6b04007f    cmp w3, w4
 834:   5400024b    b.lt    87c <_Z9testWhilei+0xbc>
 838:   11000841    add w1, w2, #0x2
 83c:   8b24c000    add x0, x0, w4, sxtw
 840:   6b01007f    cmp w3, w1
 844:   540001cb    b.lt    87c <_Z9testWhilei+0xbc>
 848:   11000c44    add w4, w2, #0x3
 84c:   8b21c000    add x0, x0, w1, sxtw
 850:   6b04007f    cmp w3, w4
 854:   5400014b    b.lt    87c <_Z9testWhilei+0xbc>
 858:   11001041    add w1, w2, #0x4
 85c:   8b24c000    add x0, x0, w4, sxtw
 860:   6b01007f    cmp w3, w1
 864:   540000cb    b.lt    87c <_Z9testWhilei+0xbc>
 868:   11001442    add w2, w2, #0x5
 86c:   8b21c000    add x0, x0, w1, sxtw
 870:   6b02007f    cmp w3, w2
 874:   8b22c001    add x1, x0, w2, sxtw
 878:   9a80a020    csel    x0, x1, x0, ge
 87c:   d65f03c0    ret
 880:   d2800000    mov x0, #0x0                    // #0
 884:   52800002    mov w2, #0x0                    // #0
 888:   17ffffe8    b   828 <_Z9testWhilei+0x68>
 88c:   d2800000    mov x0, #0x0                    // #0
 890:   d65f03c0    ret
 894:   d503201f    nop
 898:   d503201f    nop
 89c:   d503201f    nop
 8a0:   00000000    .inst   0x00000000 ; undefined
 8a4:   00000001    .inst   0x00000001 ; undefined
 8a8:   00000002    .inst   0x00000002 ; undefined
 8ac:   00000003    .inst   0x00000003 ; undefined

篇幅所限,另两个就不列举了。

x86_64的循环结构

x86不甘人后,也动用了MMX整数的SIMD指令来完成这个小循环。。。

0000000000000760 <_Z9testWhilei>:
 760:   85 ff                   test   %edi,%edi
 762:   0f 88 48 01 00 00       js     8b0 <_Z9testWhilei+0x150>
 768:   8d 47 fd                lea    -0x3(%rdi),%eax
 76b:   8d 77 01                lea    0x1(%rdi),%esi
 76e:   c1 e8 02                shr    $0x2,%eax
 771:   83 c0 01                add    $0x1,%eax
 774:   83 ff 0e                cmp    $0xe,%edi
 777:   8d 14 85 00 00 00 00    lea    0x0(,%rax,4),%edx
 77e:   0f 8e 4c 01 00 00       jle    8d0 <_Z9testWhilei+0x170>
 784:   66 0f 6f 1d 34 05 00    movdqa 0x534(%rip),%xmm3        # cc0 <Java_xulun_testcppjni2_TestJniCpp_test+0x30>
 78b:   00 
 78c:   31 c9                   xor    %ecx,%ecx
 78e:   66 0f 6f 0d 1a 05 00    movdqa 0x51a(%rip),%xmm1        # cb0 <Java_xulun_testcppjni2_TestJniCpp_test+0x20>
 795:   00 
 796:   66 0f ef c0             pxor   %xmm0,%xmm0
 79a:   66 0f 38 25 d1          pmovsxdq %xmm1,%xmm2
 79f:   83 c1 01                add    $0x1,%ecx
 7a2:   66 0f d4 c2             paddq  %xmm2,%xmm0
 7a6:   66 0f 6f d1             movdqa %xmm1,%xmm2
 7aa:   66 0f 73 da 08          psrldq $0x8,%xmm2
 7af:   39 c8                   cmp    %ecx,%eax
 7b1:   66 0f 38 25 d2          pmovsxdq %xmm2,%xmm2
 7b6:   66 0f fe cb             paddd  %xmm3,%xmm1
 7ba:   66 0f d4 c2             paddq  %xmm2,%xmm0
 7be:   77 da                   ja     79a <_Z9testWhilei+0x3a>
 7c0:   66 0f 6f c8             movdqa %xmm0,%xmm1
 7c4:   39 d6                   cmp    %edx,%esi
 7c6:   66 0f 73 d9 08          psrldq $0x8,%xmm1
 7cb:   66 0f d4 c1             paddq  %xmm1,%xmm0
 7cf:   66 48 0f 7e c0          movq   %xmm0,%rax
 7d4:   0f 84 ee 00 00 00       je     8c8 <_Z9testWhilei+0x168>
 7da:   48 63 ca                movslq %edx,%rcx
 7dd:   48 01 c8                add    %rcx,%rax
 7e0:   8d 4a 01                lea    0x1(%rdx),%ecx
 7e3:   39 cf                   cmp    %ecx,%edi
 7e5:   0f 8c d5 00 00 00       jl     8c0 <_Z9testWhilei+0x160>
 7eb:   48 63 c9                movslq %ecx,%rcx
 7ee:   48 01 c8                add    %rcx,%rax
 7f1:   8d 4a 02                lea    0x2(%rdx),%ecx
 7f4:   39 cf                   cmp    %ecx,%edi
 7f6:   0f 8c c4 00 00 00       jl     8c0 <_Z9testWhilei+0x160>
 7fc:   48 63 c9                movslq %ecx,%rcx
 7ff:   48 01 c8                add    %rcx,%rax
 802:   8d 4a 03                lea    0x3(%rdx),%ecx
 805:   39 cf                   cmp    %ecx,%edi
 807:   0f 8c b3 00 00 00       jl     8c0 <_Z9testWhilei+0x160>
 80d:   48 63 c9                movslq %ecx,%rcx
 810:   48 01 c8                add    %rcx,%rax
 813:   8d 4a 04                lea    0x4(%rdx),%ecx
 816:   39 cf                   cmp    %ecx,%edi
 818:   0f 8c a2 00 00 00       jl     8c0 <_Z9testWhilei+0x160>
 81e:   48 63 c9                movslq %ecx,%rcx
 821:   48 01 c8                add    %rcx,%rax
 824:   8d 4a 05                lea    0x5(%rdx),%ecx
 827:   39 cf                   cmp    %ecx,%edi
 829:   0f 8c 91 00 00 00       jl     8c0 <_Z9testWhilei+0x160>
 82f:   48 63 c9                movslq %ecx,%rcx
 832:   48 01 c8                add    %rcx,%rax
 835:   8d 4a 06                lea    0x6(%rdx),%ecx
 838:   39 cf                   cmp    %ecx,%edi
 83a:   0f 8c 80 00 00 00       jl     8c0 <_Z9testWhilei+0x160>
 840:   48 63 c9                movslq %ecx,%rcx
 843:   48 01 c8                add    %rcx,%rax
 846:   8d 4a 07                lea    0x7(%rdx),%ecx
 849:   39 cf                   cmp    %ecx,%edi
 84b:   7c 73                   jl     8c0 <_Z9testWhilei+0x160>
 84d:   48 63 c9                movslq %ecx,%rcx
 850:   48 01 c8                add    %rcx,%rax
 853:   8d 4a 08                lea    0x8(%rdx),%ecx
 856:   39 cf                   cmp    %ecx,%edi
 858:   7c 66                   jl     8c

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
Handler机制算是我入门源码的第一节。看得比较仔细。体会较多。mark一下。 顺序:先科普一下Handler基本功,然后再细讲下源码 一、Handler目的: 目的:Handler机制来处理了子线程去更新UI线程控件问题。 二、handler,messagequeue,looper,message关系图: 其实各种书籍上都有这么一张图。但是主要是学习源码,所以还是自己手画一张“流程图”。 三、handler知识点总结: ( 若以下总结都能理解,那么可以不再看本文后续源码分析; ) 1)handler、

ART世界探险(5) - 计算指令 - 2016-07-25 18:07:28

ART世界探险(5) - 计算指令 整数运算 Java的整型运算 我们先看看JVM是如何处理这些基本整数运算的吧。 public static long add ( long a, long b){ return a+b; } public static long sub ( long a, long b){ return a-b; } public static long mul ( long a, long b){ return a*b; } public static long div ( long
大部分的软件, 但凡包含登录注册的, 基本都会有选择头像功能, 而其中做的比较有逼格的, 一般会有一个选择框可以裁剪照片。 本文所需要实现的就是这样一种有 逼格 的效果: 右上角加了个图片框,按下确定可以裁剪正方形区域里的图片并显示在右上角。 实现思路: 1:首先需要自定义一个ZoomImageView来显示我们需要的图片,这个View需要让图片能够以合适的位置展现在当前布局的图片展示区域内(合适的位置值的是:如果图片长度大于屏幕,则压缩图片长度至屏幕宽度,高度等比压缩并居中显示,如果图片高度大于屏幕,则

注解使用入门(一) - 2016-07-25 18:07:18

注解使用入门(一) 本篇博客要讲解主要分为以下几个问题 注解的相关知识点 基于运行时的注解的例子解析说明 至于关于编译时的注解,待下篇博客的时候会结合例子讲解一下,目前我也正在学习当中 注解的相关知识点 提到注解,大多数人应该都不默认,在我们程序中见到的@Override,@Deprected,@SupressWarnings等等,这些都是注解,只不过是系统自己封装好的,而我们平时比较少去深入理解是怎样实现的? 1)什么是注解(Annotation): Annotation(注解)就是Java提供了一种元

android-----我眼中的Binder - 2016-07-25 18:07:17

        Binder作为进程间通信方式(IPC)的一种,算Android中比较难理解的部分了,今天计划以自己所认识的framework层的Binder原理来做个总结,好了,我们开始吧!         Android中利用Binder通信,首先肯定需要获得Binder对象了,但是系统服务和我们自定义服务Binder对象的获取方式是不一样的,原因就在于系统服务是在系统启动的时候被注册到ServiceManegr的,我们只需要通过ServiceManager.getService(String nam
使用xml作为数据交互的载体是Android中非常重要的功能,比如天气预报数据、短信备份数据、通讯录数据都可以以xml的格式通过网络传输。 为了演示Xml数据的操作,我模拟了一个短信备份的案例。 需求:界面如图1-10所示。上面是三个Button,前两个分别对应两种不同方式生成xml,第三个Button点击后解析备份的xml文件,然后将数据展现在下面的ScrollView中。短信数据是模拟的假数据。 生成的xml格式如文件1-10。 【文件1-10】 xml文件格式 1. ?xml version="1.
这篇博客我们来介绍一下责任链模式(Chain-of-responsibility Pattern),责任联模式又称为职责链模式,是 行为型设计模式 之一。顾名思义,责任链模式中存在一个链式结构,多个节点首尾相连,每个节点都可以被拆开再连接,因此,链式结构具有很好的灵活性。将这样一种结构应用于编程领域,将每一个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首段发出,沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止,这就是责任链或者职责链的通俗定义。 转载请注明出处: h

GeekBand第十一周笔记 - 2016-07-25 17:07:19

本周的主要内容介绍Gradle,NDK,管理依赖和Git等 一、Gradle Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。 面向Java应用为主。当前其支持的语言限于Java、Groovy和Scala,计划未来将支持更多的语言。 Coding只是软件开发中的一个部分 编译源代码 运行单元测试和集成测试 执行静态代码分析,生成分析报告 创建分布版本 部署到目标环
在安卓开发中,谷歌已经为我们提供了许多原生控件,基本上能够满足我们日常的开发需求,但是某些项目中原生控件可能达不到产品所要求的各式各样的酷炫效果或功能效果,这个时候我们只能自己自定义控件来满足项目需求,我们知道自定义控件包括三种方式: 1继承控件,即继承谷歌提供的原生控件,在此基础上提供一些原生控件不具备的功能,如github上各种酷炫效果的开源组件基本上都是采用的这种方式. 2组合控件:即组合多个原生控件来达到某些单个原生控件原本不具备的功能,这个在日常开发中应该是使用的比较多的,如基本上每个App都存

Android多点触摸交互处理 - 2016-07-25 17:07:15

安卓手机中,多点触摸是是最基本的操作,下面就使用程序进行演示多点触摸操作 一、获取触摸事件中的点击,移动和抬起事件,创建新的安卓项目,如下面代码所示,分别为MainActivity类代码和Layout布局文件,用于实现获取点击事件 1.1、MainActivity类中代码,代码中为布局对象root添加监听事件,使用switch进行对屏幕时间进行判断,用于判断事件的按下还是移动,在代码中      root=(RelativeLayout) findViewById(R.id.content);用于绑定布局