已经许久没有更新自己的博客或者其他日志了,因为实在是想不到怎么写才能表述心情。
母亲去世一年有余了,这么一年多的心情如果非要用一个词来概括,那应该是空白吧。
四年前,不顾一切从成都来到陌生的杭州,为了给家里面一个更好的未来。四年前,还相信着牛逼的技术能改变一切,怀抱着一个简单而单纯的梦,做自己想做的,成为自己想成为的人。
然而直到母亲去世,一切仿佛都失去了意义。失去了来到杭州的意义,也失去了生活的热忱。也失去了爱我的人。
又想起去年的时候我也还是有女朋友的。但是就算我们跨越上千里的距离能见,心的距离却好像只进了一点点。无力,发现想要一个拥抱也显得无足奢侈。我希望的爱不应当是这样。于是去年,和女朋友也分了手。
忽然间明白了好友说的爱应该是陪伴这句话的意义,其实我也没有对母亲做到陪伴。母亲因为有风湿,所以行动不便,然而我也没有陪伴在她身边。大家都在耻笑跳广场舞的大妈的时候,我却好想好想妈妈能去跳一跳,然而不管什么时候其实只是奢望。
在母亲更需要我陪伴的时候,我却想为了美好的将来更能让母亲过得更好,努力工作。然而当我已经能做到轻松买车买房的时候,子欲养而亲不在的痛苦才顿觉心中。
现在,工作一切很好。可惜就算我已经成为了想成为的人,但是我想那个最爱我的女人,世上或许再也找不到了吧。或许,我也又再次不知道什么是爱和孤独。
小时候我妈和我爸天天打架,很讨厌我爸,抽烟喝酒打架算什么男人,让女人哭的男人才不是好男人。但是我爸走那天,妈在床边哭得很伤心,爱是这样的么?
小姨和姨爹,我以前很羡慕他们,家庭和睦而且有乐趣,但是现在闹离婚几年。小姨也直接到外地工作。爱情是这样的么?
那天,我没有哭。之后的某天, 小姨问我觉不觉得孤单。我说不,我想其实是我不知道什么时候,已经习惯了孤独吧。或许真觉得孤独的那天,养只猫猫来陪我吧。未来,空白。
依赖
本库依赖xdebug的code_coverage功能
composer (可选)
安装和加载
最简使用方式如下,以常用的wordpress为例:
在代码开始的入口位置加上
- include “phpcodecoveragesniffer/none_composer_loader.php”;
- SimpleCodeSnifferRunner::init(“ccs”);
如果你是用composer加载的本库,
依赖中加入
- “require” : {
- “princehaku/phpcodecoveragesniffer” : “dev-master”
- },
在loader后加上
- SimpleCodeSnifferRunner::init(“ccs”);
开始使用
在你当前的站点上使用request参数即可开始使用
http://wp.loc.techest.net/?code_collect=true
然后页面右下角能看到一个show code coverage graph
点击后就能看到本次请求的代码逻辑覆盖情况。 (注: 如果报错了,请根据报错信息检查下权限。)
如下图:
附表:
参数名 值 作用
code_collect true|false 开启收集模式
collect_mode NORAML|APPEND 收集模式区别,默认是NORMAL,每次请求都会重新收集,不叠加收集数据
代码地址
https://github.com/princehaku/phpcodecoveragesniffer
前段时间有一个googlestable.com。
但是呢。它是http协议的。于是突发奇想根据googlestable代理的原理
弄一个双向https的代理应该可行了
要做的事情
首先我们需要一个nginx
wget http://nginx.org/download/nginx-1.7.2.tar.gz
tar xvf nginx*.tar.gz
./configure –prefix=/opt/net.techest/tpanel/server/nginx-1.7.2 –with-http_ssl_module –with-http_sub_module
这里注意需要两个附加模块。第一个即ssl加密模块,第二个用来做响应的替换
因为没有交钱,所以得找个地方,签名生成为我们的服务器生成一个自己用的证书
openssl req -new -x509 -nodes -out server.crt -keyout server.key
上部命令会生成两个文件,按他们的路径配置如下的nginx配置
server {
listen 443;
server_name g.techest.net;
keepalive_timeout 60m;
access_log /home/techest/logs/g.techest.net.nginx_access.log main;
ssl on;
ssl_certificate /opt/net.techest/tpanel/etc/sslkey/server.crt;
ssl_certificate_key /opt/net.techest/tpanel/etc/sslkey/server.key;
ssl_session_timeout 60m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location / {
client_max_body_size 8m;
proxy_connect_timeout 15s;
proxy_send_timeout 1m;
proxy_read_timeout 1m;
proxy_buffer_size 32k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
# 需要访问的网站
proxy_pass https://www.google.com.hk;
# 设置一下访问头
proxy_set_header Host www.google.com.hk;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 把cookie也代理过去
proxy_set_header Cookie $http_cookie;
proxy_set_header “Accept-Encoding” “”;
# 替换远端返回的cookie的作用域
proxy_cookie_domain ~\.([a-z]+\.[a-z]+)$ $host;
# 替换远端的302重定向
proxy_redirect ~*(.*)$ /;
# 统一替换远端响应
sub_filter “google.com.hk” “g.techest.net”;
sub_filter_types “*”;
sub_filter_once off;
}
# 防止google擅自主张打开了gzip
add_header Set-Cookie “GZ=Z=0;Domain=$host;Path=/;Max-Age=31536000”;
}
说明一下几个配置
- 最后那个地方是因为google新版使用cookie里面的GZ来决定是否开启gzip,优先级比上面写的Accept-Encoding还要高
- sub_filter只能替换一次,本来想用nginxlua来替换的,结果安装有问题,放弃了。而且注意如果服务端返回的是压缩数据就没有效果了
- proxy_cookie_domain可以强制把远程返回的cookie域改写掉。这样cookie和session都打通了
pyrailgun一点点在更新
最近我发布了新的0.25版本,修正了一个crash问题,同时文档也完善了许多
这个工具代码量不多,但是非常实用,也欢迎大家一起贡献源码
需要 Python2.7 版本,其他依赖安装的时候会自动解决
功能
安装
- 从pip安装
pip install pyrailgun
- 源码安装
python setup.py install
语法
例子
其他
更新
- 0.25 fix 一个crash问题
- 0.24 受版权限制,替换webbroser为自己写的版本 去除yaml的支持
使用场景
对于不同大小的背景图片,我们常常会遇到如下情形。
比如我要制作如下的两个按钮
其实他们的背景都是同样的样式但是他们的大小和范围不一致
我们可能会尝试使用drawable进行自己写xml绘制背景图
但是像如上的图片如果用xml来实现会非常麻烦。
如果直接使用png作为背景,图片会自动进行分辨率缩放,看起来就像糊掉了
比如这样
所以这个时候9patch就派上了用场
它可以在保持原图片的部分区域同时缩放指定的区域.
这样边框就不会模糊了
缩放原理
首先它会对我们的图片外框各增加1px
然后通过黑线围城的范围来决定图片的缩放方式和内容区域
上边的黑线和左边的黑线一起围成一个区域 就是你图片允许任意调整的区域
可以单独使用表示横向或者纵向拉伸
比如如上图的按钮,我们允许中间高亮部分进行横向缩放,同时允许中间横线部分纵向缩放
右边的和下边的黑线围成的区域表示你的内容允许绘制的区域
android在绘制9path图的时候会将此区域的padding附加到组件上面
制作9patch
在Android SDK路径下
ANDROID_HOME/tools里你会找到一个draw9patch
用它打开你需要的图片
mac和linux的open在顶部。你也可以把png文件拖进来
然后就可以画黑线,按shift可以擦除画的线
你可以点开下面的show content和show pathes来预览效果
右侧的三张图即在不同图片分辨率下的展示情况,紫色部分是填充内容的区域
(我的图片的字是在图上的,它不是真正的填充内容哦)
左侧绿色部分表示不会被缩放的区域
注意的几点
黑线是不能断开的,否则android系统会报错
一般建议缩放区域和填充内容区域相同
9patch制作的时候的红线是android4.3后新增的特性,用于去掉你不想要的部分 【
参考】
参考文档:
http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
http://developer.android.com/tools/help/draw9patch.html
http://stackoverflow.com/questions/11406521/android-9-patch-tool-what-is-the-new-layout-bounds-feature/11854891#11854891
注意:
1. 下载tcpdump http://www.strazzere.com/android/tcpdump
[download id=”46″]
2. 执行下面命令 传输到手机里面,记得打开调试模式
adb push ./tcpdump /tmp/tcpdump
3. 改变执行权限
adb shell chmod 755 /tmp/tcpdump
4.
adb shell, su获得root权限
5.
cd /tmp
./tcpdump -i any -p -s 0 -w /sdcard/capture.pcap
一些命令参数:
# “-i any”: listen on any network interface
# “-p”: disable promiscuous mode (doesn’t work anyway)
# “-s 0”: capture the entire packet
# “-w”: write packets to a file (rather than printing to stdout)
… do whatever you want to capture, then ^C to stop it …
6. 把输出的文件传回电脑
adb pull /sdcard/capture.pcap ~/
7. 在电脑上用wireshark打开capture.pcap即可分析log
最近需要实现一个如下图所示的列表
但是系统提供的GridView抑或是ListView均不能实现item自动排列
于是自己实现了一个
核心在于自己实现了adaper和view添加的事件,添加的时候决定是否生成一个新的line来容纳item
另外注意这个实现有一处优化的地方。
即若到第三行的时候,第三行放不下,会尝试从第一行开始计算,这样可以尽可能保证每行都是好看的效果
-
-
- /**
- * Copyright 2013
- * Created on : 13-11-27 , 上午11:53
- * Author : haku
- * Blog : http://haku.hk
- */
- public class AutoFitLinearLayout extends LinearLayout {
-
- private DataSetObserver obv;
- private BaseAdapter adapter;
- private ArrayList<LinearLayout> lineViews = new ArrayList<LinearLayout>();
-
- private AdapterView.OnItemClickListener itemClickListener;
-
- private class ItemProxyClickListener implements OnClickListener {
- int pos;
-
- ItemProxyClickListener(int pos) {
- this.pos = pos;
- }
-
- @Override
- public void onClick(View v) {
- itemClickListener.onItemClick(null, v, pos, 0);
- }
- }
-
- public AutoFitLinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- this.setOrientation(LinearLayout.VERTICAL);
- }
-
- public AutoFitLinearLayout(Context context) {
- super(context);
- this.setOrientation(LinearLayout.VERTICAL);
- }
-
- /**
- * 清空绑定view
- */
- public void reset() {
- int total = lineViews.size();
- for (int i = 0; i < total; i++) {
- this.removeView(lineViews.get(i));
- }
- lineViews.clear();
- }
-
- /**
- * @param adp
- */
- public void setAdapter(BaseAdapter adp) {
- adapter = adp;
- obv = new DataSetObserver() {
- @Override
- public void onChanged() {
- super.onChanged();
- reset();
- int total = adapter.getCount();
- for (int i = 0; i < total; i++) {
- View v = adapter.getView(i, null, getLastLineHolder());
- if (getItemClickListener() != null) {
- v.setOnClickListener(new ItemProxyClickListener(i));
- }
- addToSuitableLayout(v);
- }
- }
- };
- adapter.registerDataSetObserver(this.obv);
- }
-
- public void addToSuitableLayout(View v) {
- LinearLayout suitableLayout = getBestLineHolder(v);
- suitableLayout.addView(v);
- // 添加子view后重新计算宽度
- suitableLayout.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- }
-
- /**
- * 添加一个水平的layout
- *
- * @return
- */
- public LinearLayout addNewLineHolder() {
- LinearLayout v = new LinearLayout(this.getContext());
-
- LayoutParams layoutParams = new LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
-
- v.setOrientation(LinearLayout.HORIZONTAL);
- v.setLayoutParams(layoutParams);
- lineViews.add(v);
- this.addView(v);
- return v;
- }
-
- /**
- * 自动计算宽度后反馈line holder
- *
- * @return
- */
- public LinearLayout getBestLineHolder(View v) {
- // 计算子view的宽度和margin
- v.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- int viewWidth = v.getMeasuredWidth();
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) v.getLayoutParams();
-
- if (lineViews.isEmpty()) {
- this.addNewLineHolder();
- }
- LinearLayout lHolder;
- // 遍历所有存在的line,计算剩余宽度,如果适合就返回
- for (int i = 0, size = lineViews.size(); i < size; i++) {
- lHolder = lineViews.get(i);
- int lineMaxWidth = lHolder.getMeasuredWidth();
- if (lineMaxWidth + viewWidth + lp.leftMargin + lp.rightMargin < this.getMeasuredWidth()) {
- return lHolder;
- }
- }
- lHolder = this.addNewLineHolder();
- return lHolder;
- }
-
- /**
- * @return
- */
- public LinearLayout getLastLineHolder() {
- if (lineViews.isEmpty()) {
- this.addNewLineHolder();
- }
- // 得到最后一行,计算其剩余宽度
- LinearLayout lHolder = lineViews.get(lineViews.size() – 1);
- return lHolder;
- }
-
- public void setOnItemClickListener(AdapterView.OnItemClickListener itemClickListener) {
- this.itemClickListener = itemClickListener;
- }
-
- public AdapterView.OnItemClickListener getItemClickListener() {
- return itemClickListener;
- }
- }
一直以来。困扰大家的莫过于android的模拟器乌龟一样的速度。
这大大增加了调试的难度和开发进度。
搜寻了很久找到几个不错的办法终于找到一个办法可以让模拟器速度大幅提升。
方案1:Intel Haxm
传说中的Intel Haxm, intel提供的虚拟硬件加速功能。
官方也给出了非常详尽的安装指南,还支持mac和linux哦
下载地址http://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager/
只需要两个先决条件
- You need to have the Android SDK installed. (需要高一点的sdk,sdk安装的时候能看到Intel X86 Roms的level才可以安装)
你能看到支持它的SDK还是比较多的至少2.x和4.x各有一个版本而且都很稳定
- Your computer must have an Intel processor with support for Intel VT-x, EM64T and Execute Disable(XD) Bit functionality enabled from the BIOS.
需要CPU支持VT-x特性,高级一点的应该都支持的
速度相当不错,缺点是和普通模拟器一样,经常会挂起,adb就不认识它了。
综合评价
速度(8/10)
稳定(6/10)
安装(7/10)
崩溃(6/10)
丰富(5/10)
方案2:Genymotion(推荐)
官网是http://www.genymotion.com,这货的原理是把android跑在虚拟机virtualbox里面。
所以速度和你真实电脑直接挂钩。速度杠杠的。也是同样支持三平台
个人是免费的。注册的时候
缺点也有一些,首先是每次启动前会先联网一下效验登陆信息。同时,支持的sdk其实还是集中在4.x版本。
2.3目前只有一个pre版本即使效果还不错。
当然也会偶尔假死一下,不过因为是网络adb的所以重新连上去非常方便
adb connect 192.168.56.101:5555
综合评价
速度(11/10)
稳定(8/10)
安装(6/10)
崩溃(8/10)
丰富(3/10)