知其所以然

2015.07.07 - 知其所以然(10分钟解释一个和开发相关的原理)

WEB 登录『原理』 - 曾铭

  • HTTP 是无状态协议
  • Session 服务器端简单存储
  • cookie 客户端简单存储(注意:在请求头中)

密码如何存储

  • 明文存储
  • md5 碰撞库破解 md5(pwd)
  • md5+salt md5(pwd+salt) salt pwd
  • sha1……都能用,千万不要自己实现散列算法

一个登录的过程

  • 明文密码
  • session_id, access_token, token
  • 第三方登录:OAuth2, OpenID

iBeacon - 潘君

  • BLE

    • RSSI(Received Signal Strength Indicator)
    • 唯一标识码
    • 例: 防丢器
  • 应用场景

    • 配合微信摇一摇
    • 商城导购
    • 地下停车库导航
  • 室内定位

    • 标签定位
    • 三角定位
    • 指纹定位

andoid虚拟机 - 吴明

  • 系统框架对比android vs ios
  • ios系统框架
  • android系统框架
  • Dalvik虚拟机

    • Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础。其指令集基于寄存器架构,执行其特有的文件格式——dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它的核心内容是实现库(libdvm.so),大体由C语言实现。依赖于Linux内核的一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上表现出的高性能。每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
  • Android系统是以Linux系统为底层构建的,Android系统是开源(源代码公开)的,Android系统势必会适配到不同硬件配置的设备上,因此谷歌为了降低应用的开发难度在Linux底层之上构筑了一个名为“Dalvik”的虚拟机。

  • 一个应用,一个虚拟机实例,一个进程!!!
  • android虚拟机详细

  • 其他:

    • ART模式:Android4.4中新加入的ART模式,该模式的完整名称是Androidruntime.
    • ART:Android 4.4开始推出的新的运行环境,在APP安装的时候使用dex2oat工具直接把DEX文件转换为机器码文件,运行的时候以机器码方式运行,可以充分利用系统性能;此外,改进的内存回收机制使得ART运行模式下的内存回收速度只有Dalvik运行时模式下的50%,也能够提升系统运行速度。

Android的Message Pool是个什么鬼(源码角度分析) - 李仙鹏

Android中,我们在线程之间通信传递通常采用Android的消息机制,而这机制传递的正是Message。

通常,我们使用Message.obtain())和Handler.obtainMessage())从Message Pool中获取Message,避免直接构造Message。

Message.obtain()源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {

synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}

从代码片中,可以看到Message是直接由sPool赋值的。

Handler.obtain()源码

1
2
3
4
5
6
7
8
9
/**
* Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
* If you don't want that facility, just call Message.obtain() instead.
*/
public final Message obtainMessage()

{
return Message.obtain(this);
}

Handler.obtain()最终还是调用Message.obtain()来获取的。

Message Pool相关源码分析

Message Pool数据结构
1
2
3
4
5
6
7
8
9
10
// sometimes we store linked lists of these things
/*package*/ Message next;

private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;

private static final int MAX_POOL_SIZE = 50;

private static boolean gCheckRecycle = true;

从代码中可以很明确的看到,Message Pool的数据结构实际就是一个链表。sPool就是一个全局的消息池,sPoolSize记录链表长度,MAX_POOL_SIZE表示链表的最大长度为50。

Message Pool如何存放Message
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/** @hide */
public static void updateCheckRecycle(int targetSdkVersion) {
if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
gCheckRecycle = false;
}
}

/**
* Return a Message instance to the global pool.
* <p>
* You MUST NOT touch the Message after calling this function because it has
* effectively been freed. It is an error to recycle a message that is currently
* enqueued or that is in the process of being delivered to a Handler.
* </p>
*/

public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}

/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/

void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;

synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}

从代码分析上看,消息池存放的核心方法就是上面的recycleUnchecked()方法:

1、将待回收的Message对象字段置空(避免因Message过大,使静态的消息池内存泄漏)。

2、以内置锁对方式(线程安全),判断当前线程池的大小是否小于50。若小于50,直接将mesaage插入到消息池链表尾部;若大于等于50,则直接丢弃掉,交由GC管理。


消费者心理学:三个趣味经济学原理 — 张超耀

  • 价格越低为什么不但不好卖,反而价格越高越好卖
  • 为什么大手大脚的浪费反而可以拯救经济?
  • 为什么免费未必就是最好的

这些经济学原理背后又有哪些逻辑在支撑,让我去探讨一下这些好玩的经济学吧。

价格越高越好卖——虚荣效应

  • 富人们一般不喜欢大众模仿他们的消费行为,这种情况就叫做虚荣效应(snob effect)。虚荣效应具体是指购买商品的时候追求与众不同的个性的现象。

  • 虚荣效应主要有以下两种表现。

    • 高档商品刚上市的时候迅速购买。这是因为,在这一瞬间并不是每个人都能享受到消费高档商品的荣誉。

    • 不论之前如何热情赞美的商品,一旦其市场占有率达到一般大众都可以消费的水平就不再继续购买。这是因为人人都能购买使用的商品既不会让人感到荣誉,也不会有高档的感觉。

大手大脚的浪费能拯救经济——节约悖论

  • 我们都知道,如果消费超过收入,就没有余钱可以储蓄,也就无法积累资金,最终只能过贫穷的生活。所以,为了成为富人我们会努力工作,有时候也会变成小气鬼,为了能储蓄更多钱而努力。

  • 这个原理对于个人是适用的,但是对于国家整体经济是否也适用呢?如果所有国民都变成小气鬼,这个国家真的能够变得更加富强吗?答案是否定的,尤其是在经济不景气的时候。让我们看看其原因何在。

  • 一旦经济进入不景气,基于对未来的担忧,人们会选择更多的储蓄进而减少消费。可是如果所有人都减少消费的话,企业的销售额就会降低,库存就会增加。随之而来的是企业只能降低生产减少雇用,而企业员工的收入就会减少。那么,对未来的担忧就会强化,人们会更加坚定地减少消费增加储蓄,于是整体经济就会陷入愈发不景气的恶性循环中。

免费未必就好——免费经济学

  • “世上没有免费的午餐”是1976年获得诺贝尔经济学奖的着名经济学家米尔顿弗里德曼(Milton Friedman)常说的一句话。

  • 有的信息粗看之下似乎是免费的,实际上经过了解后发现并不是免费的意思;或者可以解释为免费后面隐藏着某种诱饵,还可以理解为不要期待不付出代价的免费东西。就像“免费的奶酪只存在于捕鼠器上”的俄罗斯谚语一样,对免费的东西保持警惕是亘古不变的道理。

  • 看看我们周围,就能发现很多免费营销,地铁站前的免费报纸就是其中一种。曾经威胁到日报和体育报纸的免费报纸因为有很多读者,所以可以从广告收入上获得高收益。人气差的免费报纸会因为得不到足够的广告收入而被淘汰,这样的话,幸存下来的免费报纸就可以逐步占据更加有利的位置。越是资金实力雄厚的公司,在这种免费竞争中能够生存下来的概率就越大。因此,消费者也可能会面临因为垄断招致的损失。

  • 免费经济市场的另一个弊端就是对资源的浪费。以免费报纸为例,因为免费派发给消费者,所以新闻纸会被大量浪费掉。大量生产大量消费的体制会导致能源的过度使用而招致地球变暖势头的加速。”


Icon制作 - 杨志平

qq20150707-6 2x
qq20150707-11 2x

51offer的Icon的流程

qq20150707-1 2x
qq20150707-2 2x
qq20150707-3 2x
qq20150707-4 2x
qq20150707-5 2x

另一个Icon的制作的流程

qq20150707-7 2x
qq20150707-8 2x
qq20150707-9 2x
qq20150707-10 2x

Android 动画制作 - 王胜

View Animation

  • AlphaAnimation 淡入淡出效果
  • TranslateAnimation 移动效果
  • ScaleAnimation 缩放效果
  • RotateAnimation 旋转效果

原理:提供动画的起始和结束状态信息,中间的状态根据上述类里差值器算法填充
[示例参考]

Property Animation

View Animation动画比较简单,一般都是单个因素的变化,如果牵扯到复杂的动画,就显得力不从心。因此,Android 3.0 引入了属性动画。注:可通过[NineOldAndroids]项目在3.0之前的系统中使用Property Animation

原理:暴露出差值算法的回调方法,有工程师自己发挥想象,造出奇妙的动画效果。
[示例参考]

Drawable Animation

逐帧动画

原理:提供动画每个帧上的图片资源,顺序播放
[示例参考]

ClipDrawable 剪切动画

原理:提供一个背景图片,前景图片是一个ClipDrawable对象。通过线程操作ClipDrawable的剪切进度。

实例:

  • ClipDrawable 定义xml文件
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="@drawable/loading_progress"
android:gravity="bottom">

</clip>
  • 组件引用
1
2
3
4
5
6
7
8
9
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:paddingTop="5dp"
android:paddingLeft="5dp"
android:background="@drawable/loading_bg"
android:src="@drawable/clip_loading"/>

  • 线程动态改变剪切进度
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
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 如果消息是本程序发送的
if (msg.what == MSG_WHAT) {
mClipDrawable.setLevel(mProgress);
}
}
};
.......
Runnable mRunnable = new Runnable() {
@Override
public void run() {
isRunning = true;
while (isRunning) {
handler.sendEmptyMessage(MSG_WHAT);
if (mProgress > MAX_PROGRESS) {
mProgress = 0;
}
mProgress += 100;
try {
Thread.sleep(18);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};