Objc中的 Selector与函数指针

定义

函数指针

int func(int arg) {

}

int (*pfunc)(int);
pfunc = func;

Selector

@interface cls
-(int) func : int arg
@end

SEL SFunc;
SFunc = @Selector(func:int);

调用

函数指针

pfunc(1);

Selector

cls *obj = [[cls alloc]init];
[obj performSelector : SFunc withObject : 1];

Android 多窗口分屏(原生方法)

事实上KitKat已经可以实现多窗口分屏,只是功能不全,Google并没有把这个功能提供给用户。

使用am stack boxes可以查看当前系统存在的Activity Stack:

am stack boxes

output:

Box id=1 weight=0.0 vertical=false bounds=[0,38][800,1208]
Stack=
  Stack id=1 bounds=[0,38][800,1208]
    taskId=2: com.android.calendar/com.android.calendar.AllInOneActivity
    taskId=3: com.android.deskclock/com.android.deskclock.DeskClock

Box id=0 weight=0.0 vertical=false bounds=[0,38][800,1208]
Stack=
  Stack id=0 bounds=[0,38][800,1208]
    taskId=1: net.lnmcc.launcher/net.lnmcc.launcher.Launcher

从上面的输出我们看到当前有两个Stack,id分别为0和1。在Stack 1中存在了两个Task,这两个Task分别是Calender和DeskClock应用。而Launcher则是在Stack 0中。实际上,你会发现Launcher始终独占Stack 0。Android有如下规则:

  • HOME stack: This is the stack with id = 0. This stack is used by the Launcher activities. When several users run Lanchers on one device, they will all belong to this stack. Other than that, systemui activities are also launched in it.
  • Applications stack: The id for this stack could be any number. All activities that are neither Launcher apps or systemui activities are run here (for all users).

得到了上面关于Stack和Task的信息后就可以按需要使用am stack create来进行分屏显示了:

am stack create 2 1 4 0.5

效果图如下(上半屏为日历应用,下半屏为时钟应用):

Alt none 使用上面的命令你可以控制两个APP的相对位置,各自的大小等等。。。具体参数说明如下:

再次运行am stack boxes来查看一下究竟发生了什么:

am stack boxes

output:

Box id=1 weight=0.5 vertical=true bounds=[0,38][800,1208]
First child=
  Box id=2 weight=0.0 vertical=false bounds=[0,38][800,623]
  Stack=
    Stack id=2 bounds=[0,38][800,623]
      taskId=2: com.android.calendar/com.android.calendar.AllInOneActivity
Second child=
  Box id=3 weight=0.0 vertical=false bounds=[0,623][800,1208]
  Stack=
    Stack id=1 bounds=[0,623][800,1208]
      taskId=3: com.android.deskclock/com.android.deskclock.DeskClock

Box id=0 weight=0.0 vertical=false bounds=[0,38][800,1208]
Stack=
  Stack id=0 bounds=[0,38][800,1208]
    taskId=1: net.lnmcc.launcher/net.lnmcc.launcher.Launcher

我们看到Box 1中有了2个子Box,分别用来存放Calendar和DeskClock,并且bounds的值给出了他们各自的显示区域坐标。

Android 源码编译 AIDL

在Eclipse下编译AIDL基本不用做什么特殊的工作,Eclipse都帮你完成了。但是如果需要在Android Source下编译AIDL,就需要你在Android.mk中加上AIDL文件声明。

LOCAL_SRC_FILES = \
                 $(call all-java-files-under, src) \
                 src/net/lnmcc/service/IMyService.aidl

Low Memory Killer in Android

Low Memory Killer(LMK)在用户空间中指定了一组内存临界值,当其中的某个值与进程描述中的oom_adj值在同一范围时,该进程将被Kill掉。

LMK的策略记录在下面两个文件中:

  1. /sys/module/lowmemorykiller/parameters/adj 这个文件指定了发生LMK时,需要kill掉的进程号区间。
  2. /sys/module/lowmemorykiller/parameters/minfree 这个文件中储存了将导致调用LMK的空闲页面数量值。

看一个例子

adj文件的内容为:

0,58,117,176,529,1000

minfree文件的内容为:

12288,15360,18432,21504,24576,30720

这里些数组的具体含义是指: 当一个进程的空闲空间下降到了30720个页面时,系统将kill掉进程号 >= 1000的进程; 当一个进程的空闲空间下降到了24587个页面时,系统将kill掉进程号 >= 529的进程; … …

怎样让你的App不被KML

你可以在AndroidManifest.xml中的Application中增加属性

android:persistent="true"

这个属性会把你的APP提升为Android核心级别,在这个级别上的APP,即使你用ps -9也无法kill掉它(它会立刻重启)。

但是这个方法有一个限制,就是你的APP需要是系统APP,也就是说需要被push到/system/app/或者/system/priv-app/下,否则android:persistent="true"这个属性不会生效。

当你为你的APP设置了persistent后,查看一下你的APP的oom_adj值:

cat /proc/3730/oom_adj  #3730为你APP的PID

我的APP的oom_adj值为-12,从上面的LMK策略可以看到LMK将永远不会kill一个oom_adj < 0 的进程,实际上它是一个CORE_SERVICE_ADJ. (ps:源码路径frameworks/base/services/java/com/android/server/am/ActivityManagerService.java)

Vim sed 最小匹配

默认情况下vim使用的贪婪匹配,但是有时候我们需要的是最小匹配,通过 :h non-greedy 查看文档发现vim可以通过下面的方式来启用最小匹配:

使用 " \{-} "来替代通配符 "*"

比如有一个文件内容如下:

(a + b) + c)

现在需要把(a + b)替换成 x

贪婪匹配

:1,$s/(.*)/x/g

上面的命令会把文件内容替换成了:

x

因为是贪婪匹配,所有这里的表达式 (.*) 匹配到了第二个右括号。

最小匹配

:1,$s/(.\{-})/x/g

结果文件内容变成了:

x + c)

可以看出这里表达式 (.{-} 只匹配了第一个右括号。