Rebound-Android的弹簧动画库

简介

官方网站

github

Rebound是facebook出品的一个弹簧动画库,与之对应的IOS版本有一个pop动画库,也是非常的强大给力。Facebook真是互联网企业中的楷模,开源了很多的实用开源库,大赞一个!!!

讲解Rebound之前,先看看我们根据Rebound高仿的新浪微博弹出菜单,看效果图:

查看更多

OC、Swift代码注释#pragma mark

以前在我们写OC代码的时候,经常通过下面语法来为代码添加注释:

#pragma mark – Initialization 
code here...
#pragma mark – Table Managementmore 
code here...

但是,如果是Swift代码,这种写法就不好使了,下面给出Swift代码注释,Swift代码注释有三种:

  1. MARK

    // MARK: - Initialization
    code here...
    // MARK: - View Managementmore 
    code here...
    
  2. TODO

    // TODO: - XXXXXXXX
    code here...
    
  3. FIXME

    // FIXME: - XXXXXXXX
    code here...
    

Swift-?和!的区别

Swift 是一种新的编程语言,用于编写iOS,OS X 和 watchOS应用程序。Swift 结合了 C 和 Objective-C 的优点并且不受 C 兼容性的限制。Swift 采用安全的编程模式并添加了很多新特性,这将使编程更简单,更灵活,也更有趣。Swift 是基于成熟而且倍受喜爱的 Cocoa 和 Cocoa Touch 框架,它的降临将重新定义软件开发。

今天我们的主角是可选类型?和!

Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值,也就是说变量不会有默认值,所以要求使用变量之前必须要对其初始化。如果在使用变量之前不进行初始化就会报错:

var value : String
//error: variable 'stringValue' used before being initialized
let hash = value.hashValue

查看更多

Android小知识总结

onCreate中计算View的高度

可以借助getViewTreeObserver().addOnGlobalLayoutListener()来获得宽度或者高度,示例代码如下:

mWebView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mWebView.getWidth();
                mWebView.getHeight();
                //防止调用多次
                mWebView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });

PopupWindow计算高度

PopupWindow在初始化创建好后,我想知道它的高度和宽度,可以这样计算:

popupWindow.getContentView().measure(0, 0);
popupWindow.getContentView().getMeasuredWidth();
popupWindow.getContentView().getMeasuredHeight();

查看更多

IOS开发小技巧

IOS配置某个圆角大小

iOS开发中各种圆角也随处可见,最简单给控件添加圆角的方式就是给视图的layer设置corner属性了:

self.view.layer.cornerRadius = 5.f;  
self.view.layer.masksToBounds = YES;  

这种方式无法配置圆角数量(只能添加view的四个角全为圆角),无法配置某个圆角大小.

这个问题我们可以用UIBezierPath来完美解决,示例代码如下:

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.view.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii:CGSizeMake(20, 0)];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];

maskLayer.frame = self.view.bounds;

maskLayer.path = maskPath.CGPath;

self.view.layer.mask = maskLayer;

self.view.layer.cornerRadius = 5.f;
self.view.layer.masksToBounds = YES;

想要配置某个角为圆角的话,只需要指定对应的UIRectCorner即可,UIRectCorner有五个值:

UIRectCornerAllCorners 全角
UIRectCornerTopLeft    左上角
UIRectCornerTopRight   右上角
UIRectCornerBottomLeft 左下角
UIRectCornerBottomRight 右下角

UITableView分割线顶到头

我们在使用tableview时会发现分割线的左边会短一些,通常可以使用setSeparatorInset:UIEdgeInsetsZero 来解决。但是升级到XCode6之后,在iOS8里发现没有效果。下面给出解决办法:

  1. 第一步

    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {

    [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    

    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {

    [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    

    }

  1. 第二步

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
        if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
            [cell setSeparatorInset:UIEdgeInsetsZero];
        }
        if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
            [cell setLayoutMargins:UIEdgeInsetsZero];
        }
    }
    

持续更新中…

Java小知识总结

编译时、运行时

编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码。例如:Java编译器把写的java文件编译成jvm能识别的class字节码文件。

而在编译的时候会涉及到一些比如常量折叠等技术,这个以后细讲!

运行时就是代码跑起来了.被装载到内存中去了.(你的代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的).而运行时类型检查就与前面讲的编译时类型检查(或者静态类型检查)不一样.不是简单的扫描代码.而是在内存中做些操作,做些判断.

下面的代码片段中,行A和行B所标识的代码有什么区别呢?

public class ConstantFolding {

    static final  int number1 = 5;

    static final  int number2 = 6;

    static int number3 = 5;

    static int number4= 6;

    public static void main(String[ ] args) {

          int product1 = number1 * number2;         //line A

          int product2 = number3 * number4;         //line B

    }
}

在行A的代码中,product的值是在编译期计算的,行B则是在运行时计算的。如果你使用Java反编译器(例如,jd-gui)来反编译ConstantFolding.class文件的话,那么你就会从下面的结果里得到答案。

public class ConstantFolding
{
  static final int number1 = 5;
  static final int number2 = 6;
  static int number3 = 5;
  static int number4 = 6;

  public static void main(String[ ] args)
  {
      int product1 = 30;
      int product2 = number3 * number4;
  }
}

常量折叠是一种Java编译器使用的优化技术。由于final变量的值不会改变,因此就可以对它们优化。Java反编译器和javap命令都是查看编译后的代码(例如,字节码)的利器。

Android进阶之ProGuard代码混淆

简介

Proguard工具通过移除无用的代码以及使用语义隐晦的名称来重命名类、字段和方法,从而达到压缩、优化和混淆代码的目的。最终您将获得一个较小的 .apk 文件,此文件更难于进行反向工程。由于 ProGuard 会使应用更难于进行反向工程,因此当应用使用对安全性要求极高的功能时(例如,当您向应用授予许可时),您必须使用此工具。

ProGuard 已集成到 Android 构建系统,所以您无需手动调用此工具。只有当您在发布模式下构建应用时,ProGuard 才会运行,因此当您在调试模式下构建应用时,就无需处理混淆后的代码。是否运行 ProGuard 完全由您决定,但我们强烈建议您运行该工具。

本文介绍如何启用和配置 ProGuard,以及如何使用 retrace 工具解码混淆后的堆栈跟踪信息。

除了基本的Proguard混淆外,还有一些其他的混淆方式和工具。例如:混淆资源

美团资源混淆

微信资源混淆

查看更多

Android性能优化之如何避免Overdraw

什么是Overdraw?

Overdraw就是过度绘制,是指在一帧的时间内(16.67ms)像素被绘制了多次,理论上一个像素每次只绘制一次是最优的,但是由于重叠的布局导致一些像素会被多次绘制,而每次绘制都会对应到CPU的一组绘图命令和GPU的一些操作,当这个操作耗时超过16.67ms时,就会出现掉帧现象,也就是我们所说的卡顿,所以对重叠不可见元素的重复绘制会产生额外的开销,需要尽量减少Overdraw的发生。

Android提供了测量Overdraw的选项,在开发者选项-调试GPU过度绘制(Show GPU Overdraw),打开选项就可以看到当前页面Overdraw的状态,就可以观察屏幕的绘制状态。该工具会使用三种不同的颜色绘制屏幕,来指示overdraw发生在哪里以及程度如何,其中:

没有颜色: 意味着没有overdraw。像素只画了一次。

蓝色: 意味着overdraw 1倍。像素绘制了两次。大片的蓝色还是可以接受的(若整个窗口是蓝色的,可以摆脱一层)。

绿色: 意味着overdraw 2倍。像素绘制了三次。中等大小的绿色区域是可以接受的但你应该尝试优化、减少它们。

浅红: 意味着overdraw 3倍。像素绘制了四次,小范围可以接受。

暗红: 意味着overdraw 4倍。像素绘制了五次或者更多。这是错误的,要修复它们。

那么我们怎么来消灭overdraw呢?总的原则就是:尽量避免重叠不可见元素的绘制,基于这个原则,我们大概可以想出以下几招:

查看更多

Android 性能优化之--使用线程池处理异步任务

说到线程,我想大家都不陌生,因为在开发时候或多或少都会用到线程,而通常创建线程有两种方式:

  1. 继承自Thread类
  2. 实现Runnable接口

虽说这两种方式都可以创建出一个线程,不过它们之间还是有一点区别的,主要区别在于在多线程访问同一资源的情况下,用Runnable接口创建的线程可以处理同一资源,而用Thread类创建的线程则各自独立处理,各自拥有自己的资源。

所以,在Java中大多数多线程程序都是通过实现Runnable来完成的,而对于Android来说也不例外,当涉及到需要开启线程去完成某件事时,我们都会这样写:

new Thread(new Runnable() {
    @Override
    public void run() {
        //do sth .
    }
}).start();

这段代码创建了一个线程并执行,它在任务结束后GC会自动回收该线程,一切看起来如此美妙,是的,它在线程并发不多的程序中确实不错,而假如这个程序有很多地方需要开启大量线程来处理任务,那么如果还是用上述的方式去创建线程处理的话,那么将导致系统的性能表现的非常糟糕,更别说在内存有限的移动设备上,主要的影响如下:

  1. 线程的创建和销毁都需要时间,当有大量的线程创建和销毁时,那么这些时间的消耗则比较明显,将导致性能上的缺失
  2. 大量的线程创建、执行和销毁是非常耗cpu和内存的,这样将直接影响系统的吞吐量,导致性能急剧下降,如果内存资源占用的比较多,还很可能造成OOM
  3. 大量的线程的创建和销毁很容易导致GC频繁的执行,从而发生内存抖动现象,而发生了内存抖动,对于移动端来说,最大的影响就是造成界面卡顿

而针对上述所描述的问题,解决的办法归根到底就是:重用已有的线程,从而减少线程的创建。
所以这就涉及到线程池(ExecutorService)的概念了,线程池的基本作用就是进行线程的复用,下面将具体介绍线程池的使用

查看更多

Android性能优化之常见的内存泄漏

前言

对于内存泄漏,我想大家在开发中肯定都遇到过,只不过内存泄漏对我们来说并不是可见的,因为它是在堆中活动,而要想检测程序中是否有内存泄漏的产生,通常我们可以借助LeakCanary、MAT等工具来检测应用程序是否存在内存泄漏,MAT是一款强大的内存分析工具,功能繁多而复杂,而LeakCanary则是由Square开源的一款轻量第三方内存泄漏检测工具,当它检测到程序中有内存泄漏的产生时,它将以最直观的方式告诉我们该内存泄漏是由谁产生的和该内存泄漏导致谁泄漏了而不能回收,供我们复查。

最近腾讯bugly也推出了三篇关于Android内存泄漏调优的文章:

  1. 内存泄露从入门到精通三部曲之基础知识篇
  2. 内存泄露从入门到精通三部曲之排查方法篇
  3. 内存泄露从入门到精通三部曲之常见原因与用户实践

Realm同样给出了性能优化文章:

10条提升Android性能的建议

查看更多