08.29.10
Posted in Join's blog
at 10:28 PM
当年学车的最后一考,最后一停考官让我“瞄准前面第三根电线杆子”。
我只顾瞄准那第三根电线杆子,方向盘右打不够,把车停在路中间了。
车内气氛相当尴尬,敬爱的驾校校长亲自坐在后座,我驾驶的皮卡趴在马路中间,距离道鸭子足有三米,当时正值下班高峰,两边都有车流呼呼驶过。寂静了大概五秒钟吧,还是考官懂得缓和气氛,说:“你这停的什么破玩意儿?!赶紧给我下去!”
我不忘考试注意事项的最后一步,先瞭望一下左后方。本来这是走形式的一步,结果我真的发现门外有好多车呼呼地擦着观后镜飞驰而过。我回身跟考官说:“下不去啊,车太多了。”考官胡子都要气掉了,大吼:“你不停路当间儿能下不去嘛?!”
后来还是校长面子大,竟然把我整pass了。临解散拍拍我肩膀,语重心长地说:“你刚才停的什么破玩意儿啊?!”
岁月如哥只是个传说,时间转眼就到了刚才。
下班回家,缓缓驶向属于我的露天车位。有人站在那里。一男一女,在吵架,哇哇地。男的赤膊加小短裤,女的穿了一件睡裙,蕾丝的……这么三俗的造型,这么不和谐的景象,发生在我的车位上,我完全困惑掉了。寻常情况下,人看到车来了,应该走开才对吧,可是这两个人这么不寻常的造型,决定了他们采取不寻常的对策:岿然不动,继续吵啊吵。本司机被彻底忽略了。
要说这二位站这地方也有水平,他们占据车位很小的一部分,让我可以把车泊进,但是泊完后车头能不能刮到大姐裙摆的蕾丝边就不好说了呀。当时我是尴尬地犹豫了一下的,想换个地儿,但是环顾四方,大礼拜天晚上的,大家的车子都休息了,只有我这种卢瑟才这么晚下班回家,已经没的车位了。我必须绕过他俩把车泊进!
车尾慢慢地先绕进去,大哥说:“……我后来没说啥吧……”。慢慢往后倒,大姐说:“……那不寺因为我瞪了你一眼嘛……”。
回轮,车头往里进,哎呀,灯光照到他俩了……蕾丝啊……关掉大灯,给他俩一点私人空间。车头摆正,哎呀,因为怕碰到他们,太保守,小半个车身都在外边。
大哥说:“……不管怎么样我没说话吧……”。
不行啊,半夜这里要过搅拌车,这样子是绝对不行的。
大姐说:“……你说的还少么……”
车头挑出来再来一次。
车灯关了,难度太大了。这两人吵得太投入了,一丁点给我挪地方的意思都没有。
右打轮儿。大哥说:“……我就说那么两句话,你看你弄得,至于么……”。
TMD黑灯瞎火看不见道鸭子啊。大姐说:“……我说至于就至于……”。
差不多了,回轮。大哥说:“……以前也说过啊,没见你这么大反应啊……”。
控制车头不要碰到蕾丝边。大姐说:“……我今天实在受不了了……”。
快搞定了。但是车尾离后车太近,还得往前上上。大哥说:“……那你也太不给我面子了,都是朋友在那……”。
没开灯真要命啊,黑乎乎看不清楚,要完全靠感觉才能不碰到蕾丝边。大姐说:“……我就是说给他们听……”。
可以了,虽然有点歪,但是特殊情况,顾不了那么多了。已经够尴尬了。熄火关门锁车回家了。
大哥说:“……你悄悄跟我说就完了呗……”。
大姐说:“……这本来就不是你一个人的事儿啊……”。
遗憾啊,临走也没听明白是怎么回事。
走到一半儿,我擦,手机没拿……
还得回去……
大哥大姐不会以为我特意回去听热闹吧。
低头飘回车里拿手机。
再锁车,不好意思啊,锁门时车灯要闪两下……大姐的蕾丝边轻轻飘动……
大哥说:“……那你说我以后该怎么办吧……”。
大姐说……大姐说……
大姐说:“……以后?以后打牌就悄悄打,别老跟对门说话!!!”
我在秋风中萧瑟了。
靠边停车不容易。
鄙视打滚子说话的。
Permalink
07.20.10
Posted in Join's blog
at 1:07 PM
[原作者是Gilles Debunne,身份不详...]
要想搞出一个反应迅速的Android应用程序,一个很好的做法就是确保在主UI线程里执行尽量少的代码。任何有可能花费较长时间来执行的代码如果在主UI线程执行,则会让程序挂起无法响应用户的操作,所以应该放到一个单独的线程里执行。典型的例子就是与网络通信相关的操作了,因为通过网络收发信息的快慢我们无法预测,有可能“biu”地一下就搞定了,也有可能磨磨唧唧半天。用户心情好的话可能会容忍一点点迟延,而且前提是你给出了必要的提示,但是一个看上去根本不动貌似嗝儿屁的程序……(译注:就好比Ajax技术出现之前的网页,用户可以习惯短时间的载入,但是一个载入了半天都是空白的浏览器窗口就常常让那个拨号时代的我们感到困惑和抓狂。)
在这篇文章中,我们将创建一个简单的图片下载程序来演示一下多线程模式。我们将从网上下载一坨图片,然后用这些图片生成一个缩略图列表。创建一个异步工作的任务,让它在后台下载图片,会让我们的程序看上去更快。(译注:这里我加上“看上去”,因为我认为所谓多线程让程序更快,更多的意义在于“提高对用户操作的响应”。包括本文题目,所谓的“高性能”,主要指的还是避免UI的硬直(格斗游戏术语,请自行google)、挂起。毕竟多线程无法避免代码固有的主要资源开销。)
一个图片下载器
从web下载图片很简单,使用SDK提供的HTTP相关的类即可实现。下面是一个简单的实现。
(译注:下面用到的AndroidHttpClient等类从2.2版,也就是API Level 8才开始提供。请2.1以下各位从代码领会精神即可。直接用HttpClient应该亦可实现。)
static Bitmap downloadBitmap(String url) {
final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// Could provide a more explicit error message for IOException or IllegalStateException
getRequest.abort();
Log.w("ImageDownloader", "Error while retrieving bitmap from " + url, e.toString());
} finally {
if (client != null) {
client.close();
}
}
return null;
}
首先我们创建了一个HTTP客户端和HTTP请求。如果请求成功,就把响应中包含的图片内容解码成位图格式并返回,以备后续使用。另外补充一句,为了让程序可以访问网络,必须在程序的manifest文件中声明使用INTERNET。
注意:旧版的BitmapFactory.decodeStream有个bug,可能使得在网络较慢的时候无法正常工作。可以使用FlushedInputStream(inputStream)代替原始的inputStream来解决这个问题。下面是这个helper class的实现:
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int byte = read();
if (byte < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
这个类可以保证skip()确实跳过了参数提供的字节数,直到流文件的末尾。
如果你在ListAdapter的getView方法中直接使用上面的downloadBitmap方法,结果可以想象的出,随着我们滚动屏幕,一定是一顿一顿很不爽的。因为每显示一个新的view,都必须等待一张图片完成下载,势必会影响滚屏的流畅度。
正是因为这想都想得出来的糟糕体验,AndroidHttpClient根本就不允许在主线程里启动!上面的代码在主线程里将会提示“本线程无法进行HTTP请求”。如果你不见棺材不落泪,说啥也要亲手试试这糟糕的用户体验的话,可以用DefaultHttpClient代替AndroidHttpClient,给自己一个交代。
异步任务
AsyncTask类提供了一个从主线程生成新任务的方法。让我们创建一个ImageDownloader类来负责生成任务。这个类将提供一个download方法,从指定URL下载图片,并在ImageView里显示出来。
public class ImageDownloader {
public void download(String url, ImageView imageView) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
task.execute(url);
}
}
/* class BitmapDownloaderTask, see below */
}
BitmapDownloaderTask继承自AsyncTask。它真正执行图片下载的任务。任务通过execute方法启动,该方法是立即返回的,从而使得调用它的主线程代码可以迅速执行完毕。这正是我们使用AsyncTask的意义所在。下面是BitmapDownloaderTask的实现:
class BitmapDownloaderTask extends AsyncTask {
private String url;
private final WeakReference imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference(imageView);
}
@Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
// params comes from the execute() call: params[0] is the url.
return downloadBitmap(params[0]);
}
@Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
doInBackground方法是真正在单独进程中执行异步任务的代码。它调用前面介绍的downloadBitmap方法,完成下载,取得位图。
onPostExecute在任务结束后由主线程调用。它通过传入的参数得到下载回来的位图,并设置到ImageView显示(该ImageView在实例化BitmapDownloaderTask时传入)。需要注意的是这里对ImageView的引用是以WeakReference的形式保存在BitmapDownloaderTask实例里,所以在下载过程中如果activity被关掉,无法阻止activity里的ImageView被回收。因此我们必须在使用前检查imageViewReference和imageview是否为空。
这个简单的小例子演示了如何使用AsyncTask。如果你亲自动手实验一下,应该会发现这短短几行代码显著地改善了ListView的滚屏体验。推荐阅读developer.android.com的文章《Painless threading》来学习AsyncTasks的更多细节。
但是,这个基于ListView的例子暴露出一个问题。出于对内存的利用效率考虑,ListView会在用户滚屏的时候对view进行循环再利用。如果用户快速猛烈发飙般地滚屏,一个ImageView对象将会被反复使用多次。每一次它被显示出来,都会触发生成一个下载图片的任务,从而改变这个ImageView的显示内容。那么问题在哪呢?跟大部分并行程序一样,关键问题在于顺序。在我们这个例子中,没有采取任何措施保证所有下载任务按顺序完成,换句话说,无法保证先启动的任务先完成,后启动的任务后完成。这样就导致显示在list中的图片可能来自之前的任务,该任务因为花费的时间更长,所以最后结束,最终导致预期外的结果。如果你要下载的图片们是一次性绑定到一坨ImageView的,那么就不存在问题,但我们还是从大局出发,为了通用的情况,修正一下吧。
并发处理
要想解决上面提到的问题,我们需要知道并保存下载任务的顺序,以保证最后启动的任务最后结束,并完成对ImageView的更新。要达到这个目的,让每个ImageView记住自己的最后一个下载任务就可以了。我们使用一个专用的Drawable类给ImageView添加这份信息。这个Drawable类将在下载过程中临时绑定到ImageView。下面是这个DownloadedDrawable类的代码:
static class DownloadedDrawable extends ColorDrawable {
private final WeakReference bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
super(Color.BLACK);
bitmapDownloaderTaskReference =
new WeakReference(bitmapDownloaderTask);
}
public BitmapDownloaderTask getBitmapDownloaderTask() {
return bitmapDownloaderTaskReference.get();
}
}
这个实现方法引入了一个ColorDrawable,这会导致ImageView在下载过程中显示黑色的背景。需要的话,可以使用一个显示“下载中…”之类的图片代替之,换取更友好的用户界面。再提一遍,注意使用WeakReference来降低与对象实例的耦合。
让我们修改之前的代码来让这个类起作用。首先,download方法将创建这个类的实例并绑定到ImageView:
public void download(String url, ImageView imageView) {
if (cancelPotentialDownload(url, imageView)) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
task.execute(url, cookie);
}
}
cancelPotentialDownload方法将在一个新的下载开始前取消尚在进行中的下载任务。注意,这并不足以保证新开始的下载任务得到的图片一定能够被显示,因为之前的任务可能已经完成了,处于等待onPostExecute方法执行的时间点,而这个onPostExecute方法还是有可能在新任务的onPostExecute方法之后执行。
private static boolean cancelPotentialDownload(String url, ImageView imageView) {
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
if (bitmapDownloaderTask != null) {
String bitmapUrl = bitmapDownloaderTask.url;
if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
bitmapDownloaderTask.cancel(true);
} else {
// The same URL is already being downloaded.
return false;
}
}
return true;
}
cancelPotentialDownload调用AsyncTask类的cancel方法来停止进行中的下载任务。大部分情况下它返回true,所以调用它的download方法中可以开始新的下载。唯一的例外情况是如果进行中的下载任务与新任务请求的是同一个URL,我们就不取消旧任务了,让它继续下载。注意在我们这个实现方法中,如果ImageView被回收了,与其关联的下载不会停止(可以借助RecyclerListener实现)。
这个方法还调用了一个helper函数getBitmapDownloaderTask。代码很直观,不做赘述:
private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
if (imageView != null) {
Drawable drawable = imageView.getDrawable();
if (drawable instanceof DownloadedDrawable) {
DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
return downloadedDrawable.getBitmapDownloaderTask();
}
}
return null;
}
最后,必须修改一下onPostExecute方法,保证只在ImageView尚与下载进程关联的情况下绑定位图到ImageView:
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
// Change bitmap only if this process is still associated with it
if (this == bitmapDownloaderTask) {
imageView.setImageBitmap(bitmap);
}
}
嗯,做了这些修改之后,我们的ImageDownloader类基本可以提供预期的服务了。你可以在自己的项目中灵活运用这些代码或者它演示的异步思想,改善用户体验。
Demo
本文的源代码可以从Google Code获取。你可以在本文提到的三种实现方式(非异步、无并发处理以及最终版本)中切换、比较。注意,缓存大小已经被限制到10张图片以便更好地演示可能出现的问题。
进一步的工作
文中代码为了集中讨论并行问题而做了简化,因此缺少很多功能。首先ImageDownloader类应该利用缓存,特别是与ListView结合使用的时候。因为ListView在用户上下往返滚屏的时候会多次显示相同图片,而缓存可以大大降低开销。通过使用一个基于LinkedHashMap(该hashmap提供从URL到Bitmap SoftReference的映射)的LRU缓存可以很容易地实现这一点。更加复杂的缓存机制还可以依赖于本地存储。缩略图的创建、图片缩放等功能也可以考虑加进来。
本文代码已经考虑到了下载错误和超时的情况。这些情况下将会返回一个空位图。你也可以显示一张带有提示信息的图片。
本文示例的HTTP请求很简单。根据实际情况的不同(大都依赖于服务器端),可以在HTTP请求中加入各种参数或者cookie等等。
本文使用的AsyncTask类是一个把任务从主线程分离出来很简单方便的途径。你可能会用到Handler类来实现对任务流程更好的控制,比如控制并行的下载线程数,等等。
原文地址:猛击这里(在墙的那边)
Permalink
07.14.10
Posted in Join's blog
at 4:45 PM
翻开blog,发现上一篇已经是09年1月的事情了。
记得朱自清那段描述时间流逝的文字么?他说:“丫忒快了。”
初中的时候为了备考高中,经常写议论文。而“时间”,是要重点训练的题材。往往为了写这样一篇作文,搜肠刮肚,花掉周末整整一个上午的时间,在临近午饭的时候匆匆结尾:让我们善待时间,走向成功。
我心里只觉得我虐待了自己一个上午,得赶紧走向饭厅。
谈论时间这个话题实在是太沉重而又复杂了。爱叔叔和霍大爷都没有太拎得清,所以我还是不要太投入的好。
其实时间于我身上最大的体现是年龄。按说我三十不到,是个绝对意义上的年轻人,足球场上面对二十出头的大学生也可以大步一趟就甩在身后,亦或大屁股一撅顶翻在地。开始在意年龄是因为有人拿年龄说事儿。人是贱的,或者说我是贱的,当有人特别是你在意的人拿它说事儿时,你再潇洒再洒脱再脱俗也难免要犯嘀咕。我曾长时间跟自己嘀咕,试图搞清我到底是老是少,后来终于,到底是没搞明白。可我大概明白了一点就是,如果拿时间年龄说事,也许问题的关键并不在于时间或年龄,只是不想给你余地反驳或纠正。因为纵使你有天大的本领,也无法改变或阻止时间的流逝。主席说“与天斗,其乐无穷。”我觉得他老人家多少有点吹牛B了。
不过如果读者你还处在世界观尚未成形的少年,我劝你不要鸟我上面的言论。一定要有与命运与时间抗争的大无畏精神。人的理想是一条渐衰的曲线,年少时一定要有超级积极向上的态度,才能在青年时保持很积极向上,在中年时比较积极向上,在老年时积极向不向上就无所谓了。否则现在就觉得一切天注定,那不是成熟,是未老先衰。年少的时候该走的形式就要走;该写的作文就要写;该考的试就要考;该失的败就要失;该崇拜的领袖就要崇拜……因为只有经历过这些你才能学会该在乎什么不该在乎什么;该追求什么不该追求什么;该改变什么不该改变什么;该保护什么不该保护什么;该相信什么不该相信什么……
插播:twitter上流传着成龙大哥代言杀手的段子。很明显,不是成龙的问题。相反,正是因为这些产品本身没有自信,所以巴望找到一个顶级巨星拉动品牌。正所谓顽症需猛药,这恰恰说明成龙的牛B。可决定权毕竟掌握在消费者和有关部门手里,该被淘汰的总要被淘汰,该被被淘汰的总要被被淘汰。至于佳能,属于跟成龙强强联手,嗯,解释权归本作者所有,道理永远都是博主的。
低头看表,都快下班了,还有一部分工作没完成,时间确实过得忒快了。它“biu”地经过,只给书架上多日未翻的书本、案头许久未开的茶叶罐、客厅里数月未动的游戏机、抽屉里几年未阅的相册、背包里也许此生都无法送出的礼物……蒙上一层薄薄的浮灰。
是让这灰越积越厚,还是抖掉,等待时间再来经过?
Permalink
01.10.09
Posted in Join's blog
at 5:42 PM
我有个初中同学,叫Sun Chang Bin。
班里很多同学都是上了初中才开始玩足球,而Sun Chang Bin那个时候已经踢得很好了。
当时的他可以很轻松地晃过当时的我。而有时兴起,他甚至会一边带着球从我身旁绝尘而去,一边贱笑着拍我屁股一下。
这其实算是一种“侮辱”了,但我这个人生性还算厚道,特别是如果有什么地方不如别人,我会谦虚得略显懦弱。所以面对这种“侮辱”,我都是一笑了之,从不往心里去。本来踢球就是游戏,不能因为对这种玩笑气恼而坏了兴致。
直到有一天,我有点不高兴了。
因为Sun Chang Bin虚晃一下绕过我的同时,
伸手到我的兜里,
把我准备用来买汽水的两块钱掏走了。
Permalink
12.27.08
Posted in Join's blog
at 3:51 PM
本应是Staturday in Cinema的,但是奥纳的团体票柜台的队伍排到了门外。
现金购票倒是不用排队,但是60一张票,非诚勿扰。于是我满怀诚意地来到公司加班。
之前领略过本脖风格的朋友们应该能猜到吧,这注定又是意识流得满地都是的一次加班经历。
坐下先拉开抽屉拿出一盒花生,嗑一粒。别看小小一粒花生,吃完我就哭了。眼泪止不住地流。没想到我现在感情脆弱到这等程度。吃颗花生而已,泪流满面。
公司并不只有我一个人,背后的小Li,还有远处几个小伙子也在。
安静地干了一会儿活,不可思议的事情发生了,身后传来弦乐,回头一看,小Li不知从哪里变出一把吉他,正弹得爽!他告诉我曲子的名字叫《爱的罗曼司》。
随即远处传来我还在青春期就听过的“小虎队”的那个什么“把你的心我的心串一串”,顺着声音定睛一看,一个少年唱啊唱,很陶醉的样子。
本想描写一些更离谱的事情,但是看看电脑屏幕右下角的电子表,时候不早了。我交代,这篇真的不是意识流。我吃的是“芥末花生”,吃了绝对会流泪。而今晚是公司的“忘年会”,小Li要表演吉他弹奏。远处的少年侧要唱那个“串一串”……
Permalink
12.23.08
Posted in Join's blog
at 10:22 AM
有同事身先士卒,戴上新发的防静电手套去实验室摸打印机。
于是里屋的惨叫声此起彼伏。
Permalink
12.22.08
Posted in Join's blog
at 2:01 PM
为了对付静电,公司给我配发了一副防静电手套。
想象中这副套子应该充满了阳刚之气,深褐颜色,质地坚韧而柔软,贴合双手,富有弹性,极富质感和品位……
谁知拿到手里的这副,套体纯白,点缀着灰色条纹,手腕部位还用黄线勾边儿。
戴在手上,竟然还是半透明的,白色手套隐隐透出肉色……
这等不伦不类的货色,别说质感和品位了,想演个外科大夫蒋委员长小学鼓号队都不好使。
只能用来扮米老鼠。
Permalink
11.02.08
Posted in Join's blog
at 7:27 PM
我的三千烦恼丝终于还是给我带来了烦恼。
插播一句:本人已于前天傍晚返回大连。
回到正文中来。回大连下飞机后推着行李从出口往外走,边走边找前来接我的父母大人。
但是因为飞机晚点,出口积攒了太多接机的人,举着各种牌牌,上面写着一些中国人日本人韩国人男人女人的名字。
我直到走进大厅也没见到父母的身影,半年未用的号码也被移动干掉了,于是开始用肉眼再在人群中搜索……
终于啊,找到了。俩人正盯着出口呢。
我说“怎么没看着我啊?”
我妈说“原来是你啊?刚才看到了来着,我还想,这小姑娘怎么和我儿子长得这么像啊……”

Permalink
09.24.08
Posted in Join's blog
at 9:28 PM
五个月以来只要出门,就要骑车。
最远的一次因为找一家店迷了路,闷头骑了两个多小时,一抬头,发现骑到了另一座城市。
找到地图往回骑的路上,沿街是很多名车的专卖店。
穿着背心裤衩的我,骑一辆红色自行车从保时捷专卖店门口飞驰而过,沿途买一盒吉野家的牛肉饭,回家一边吃牛肉饭一边看一部从网上下载的盗版电影,然后跑到楼下同事家里凑一桌扑克打到半夜,倒头大睡后迎来第二天,上班写一些不管我写不写这个世界都不会有什么变化的狗屁程序……
因为骑车太多,现在就算不骑车,只要我走快点儿,腿就会像蹬在脚蹬子上一样做圆周运动。速度提到跑起来的话,则快得就像轮子一样了,酷似《猫和老鼠》里不知疲倦地你追我跑了几百集的汤姆与吉瑞。
Permalink
09.15.08
Posted in Join's blog
at 10:49 PM
看到此等题目,认识我的人们能想象出我现在是番什么形象么?
文字的好处在于读文字的人可以在文字内容的基础上根据自己对文字的理解在脑海中施以把抽象的文字具体化的想象。
哪怕只是短短两个字,拥有不同经历不同性格不同爱好的人对相同的文字必然有各种不同的理解,于是,此时此刻,相信我的形象在各位的脑海中一定有很多不同的版本。当然了,这些版本一定有一个共同点:长发。
把各位的想象总结到一起,存放在同一个目录下,用缩略图的方式查看,轮流安放在一个假想的我的秃头上,应该是件挺有意思的事情。不知道这里面会不会有《蛇形刁手》里的成龙,《猛龙过江》里的Bruce Lee,那不勒斯时期的马拉多纳,一脚把点球干飞的罗伯特巴乔……
他们的发型是一个时代的标志与回忆,我的发型则只是……一堆长在我脑袋上的毛发。
五个月的时间不理发,是目前我的个人记录。事实上,在大约过了两个月不到的时间之后,这个记录就早已开始随着时间的前进不停地被刷新着。我并不是因为在日本理发多么贵才选择逃避,只是我觉得日本人对发型的理解与我实在不同。我看过几个同事理发归来的“作品”,总是感觉怪怪的。我不知道自己从一个“美容室”出来后会是何种模样。我本来长得就不好看,如果再弄个无比滑稽的发型出来,不知道会是个什么效果。就这样,理发的计划一拖再拖,拖到现在,在还有一个半月就将回国的时候,似乎已经没有理由再考虑理发的事情了。这就像午休时间的电梯,如果选择了等待,那么就不要在已经等了五分钟的时候因为不耐烦而改走楼梯下楼。
头发长了才知道,我的不好看已经到了无以复加的地步。因为之前发型的不着调,始终让我抱有有一种“也许留长会变帅吧”的幻想。现在我终于发现,秃、短、中、长的发型都不适合我。这可真是个让人揪头发的问题,这意味着我已经失去了选择“哪个发型更好看”的权利,只剩下“哪个发型更不难看”的妥协。
经常能看到一些以《透过XX看世界》为题的文字,很有哲理,很有深度,很发人深省。那天我突然想起,能不能搞一个《透过头发看世界》,也玩一把深沉,让大家觉得我也很哲理很有深度很发人深省?于是我用手把头发向前梳拢,盖过额头,越过眉梢,挡住眼睛,走到窗前,看这个世界,试图感受一些很有哲理很有深度很发人深省的东西。于是我感到,很痒。
我还曾学过《少林足球》里的周星驰,用捆便当的皮筋儿在脑后扎起一个小辫儿。但是摘下皮筋儿的时候带下几根头发,非常疼。远不如用皮筋儿做个弹弓打别人家玻璃好玩儿。
因为头发变长,我的头似乎也沉了不少。上班的时候稍不注意脑袋就会不由自主地坠下去。有人误解我说上班时间打瞌睡,那可是非常的冤枉。真实原因是我的脑袋以前没有承担过这么多的头发,现在它掌握不好平衡,并不是我犯困。
Permalink