2014年6月1日 星期日

Dart : The New Platform for Scalable Web App Engineering

Google的風格就是,當某種語言/工具無法滿足需求時,就會自己創造一個全新的,Dart也是其中一個產物。
https://www.dartlang.org/

Dart的目的是要取代Javascript,因為它實在是太多問題了(Firefox : 哪會),但目前除了Chrome以外,沒人願意把DartVM綁在自己的Browser裡,不過目前Dart Code還是可以轉成Javascript(轉換後不預期你做任何修改),執行在其他的瀏覽器上面(據說Performance也比原本的Javascript Native來的好),如此創新的作法還真的讓人躍躍欲試,但是,想到許多原本用的很開心的Javascript library都要等別人包成Dart的Plugin才能使用。

基於最後的結論,我還是緩緩先。


Reference:

Wiki : http://zh.wikipedia.org/wiki/Dart

2014年5月6日 星期二

Pull-to-Refresh on Android

    Pull-to-Refresh(PTR)的功能在iOS是原本就support的功能,而在Android上面既然要靠第三方Library(現在則否)來實現,由此可見Andorid生態系的UI原件多麼貧乏;自然而然就會有開發者去寫一個類似iOS的功能:

Android-PullToRefresh : 我們產品原本也用這個,但是碰到難以延伸的問題之後就改用別的(後面會提到),難以延伸的問題來自原件直接繼承,如果你要用在GridView,那你就必須用PullToRefreshGridView,這就會碰到如果你的GridView是客製化的(可能你會用GridViewHeader,或StickyGridHeaders,這個問題來自另外一個需求,Android的GridView沒有辦法加Header跟Footer),那這個Library就會讓你傷透腦筋,有了這個設計瓶頸,使我們不得不嘗試使用ActionBar-PullToRefresh。

ActionBar-PullToRefresh : Android為了更像Android,連PTR的行為也改得跟iOS不同,也就是Refresh的時候在ActionBar上會有一條跑馬燈在奔馳著,這套Library就是採用這種實作,自然而然程式的架構也不會跟UI元件直接耦合在一起。不過使用它必須要注意的是API的版本跟ActionBar的實作方式,它推出了三種Library:

1. actionbar-pulltorefresh:library : api 14+
2. extra-actionbarcompat-pulltorefresh : api7+. 使用support-library實作ActionBar
3. extra-actionbarshelock-pulltorefresh : api7+. 使用ActionBarshelock

這套Library採用Delegate的方式與元件互動,有興趣的話可以直接看他們的example code

mPullToRefreshLayout = (PullToRefreshLayout) view.findViewById(R.id.ptr_layout);
ActionBarPullToRefresh.from(getActivity())
                    .allChildrenArePullable()
                    .listener(this)
                    .setup(mPullToRefreshLayout);

但可惜的是該套Library已經不在維護,因為Google官方的support-library(v19.02)已經默默推出了SwipeRefreshLayout;再者它跑在Amazon Kindle機器上也會有Bug,感覺是padding算錯了,所以沒有辦法跟ActionBar貼在一起,所以最後我們會採用Google官方的版本。

SwipeRefreshLayout(API 7+):他跟ActionBar-PTR不同的地方在於Animation,上者是從左到右的跑馬燈,而它從中間往外擴的跑馬燈,而且在拖拉到一半的時候不會有提示訊息擋在ActionBar上,API使用的方式也蠻像ActionBar-PRT,但目前是第一版所以有些問題需要自己修改。

1. 無法ListView/GridView無法ScrollUp : 這個問題會發生在你包Layout的時候,如果第一個元件不是List/GridView的話就會發生。
2. 拖拉時,該頁面"一定"會彈跳 : 有些Design不預期有這種行為,但現在的API架構也無法讓你取消它。


寫到最後,才發現如果把細節寫下去可能會長到太過誇張,所以這篇文章先定位成選用不同PTR Solution的Outline,而實作及設計細節就留給其他文章當作"救援投手"了。

2014年4月29日 星期二

The future of JVM : JRuby


    晚公司邀請了JRuby的Contributor : Charles Oliver Nutter來談談JRuby,也談談未來JVM會的長相。JRuby的目的是讓原本只能活在JVM的Java Code,忽然可以跟世界外的語言有所互動,Ruby是其中之一,當然還有Python(Jython),為了要辦到這件事情有許多問題需要解決。

    他提到第一點,Bootstrap Time,他用了JVM可以微調的Flag,加上Pre-load JVM的技術(Drip/NailGun/還有一個忘了),讓執行時間跟跑原本的Ruby環境差不多(個人懷疑Runtim memory可能大上好幾倍)。

    第二點是Native Code,原本的世界裡,如果Java要呼叫Native的Code只能透過JNI(例如拿process ID),他本人是非常討厭JNI,除了寫起來吃力不討好之外,也提高的平台相依性(跟JAVA的初衷Write one, Run anywhere有所抵觸),他提到新的玩意叫做Java Native Runtime(JNR)也能辦到相同的事情,除了Interface比較簡潔外,也有龐大的community再幫你解決不同平台上所需要解決的Porting問題,其目的為把所有POSIX上支援的function都有一份Java對應的實作(不過目前還沒完全支援)。

    最後他提到JAVA 7之後support的invokedynamic指令,從bytecode等級支援新的語法來提升動態語言的效能。他也提到說每個Engineer都會想要創造自己的程式語言,但礙于並非對Compiler有所專精,而且可能要寫非常多底層的Code來Optimize performance,所以有一個新的架構可以滿足/解決我們的問題,它是Graal,概念有點像是C跟LLVM,而JAVA跟Graal,實際運作是所有的Java Code不會直接Compile成Bytecode,而是Graal Representation,然後再透過Graal的IR做最佳化之後直接Run再Native Code上面;有了Graal後再搭配Truffle,它能夠讓你自己撰寫IR去Optimize你的Code(當然也可以寫JAVA),如此一來,你就可以打造一個完全屬於你的語言了(但還是跑在JVM上面)

備註:本篇文章是根據昨晚聽完簡報後所撰寫,可能技術細節的描述有所錯誤,麻煩請多多指教。

2014年3月31日 星期一

4am.tw + parallax scrolling




   天看完盧廣仲演唱會後異常熱血,喝了點小酒開始把之前hackthon的project重新從github checkout下來;這次想幫4am.tw用parallax scrolling的library(skollr)寫了另外一個版本. 資料全部來自於原本的網站(不知是否會有授權問題?);而source code(在這)。BTW因為它架在Heroku所以如果太久沒人用會呈現睡眠的狀態。

目前沒有做到很完美~歡迎大家指教。



2014年3月4日 星期二

Bolts it!


    據前一篇Deferred&Promise的討論後,我們最後選擇了Parse發佈的Bolts。這篇大概介紹一下Bolts的實際應用方式,某些部分比較像是再把官方文件在述說一次,最後再做個總結。

Q. 什麼情況下要用Bolts?
A. 所有會卡UI Thread的事情都要,包含網路存取,檔案讀寫,複雜的運算等等

Sample Code:

Task.callInBackground(new Callable<Result>() {
     @Override
     public Result call() {
         // DO SOMETHING
         return result;
     }
});


Q. 那跟AsyncTask沒什麼差別呀?
A. 沒錯,但是Bolts可以應付更複雜的情境
情境:從網路抓一份list(約一百筆資料),並將list中的個人照片抓取下來,最後放到local資料夾。

難題:當然可以把所有事情放到一個AsyncTask裡面做完,所以整個Task時間拉很長,比較好的做法是不同的工作需求可以用不同的Executor來執行,而不同的Executor可以用不同的Policy來調整(包括ThreadPool的Size,Timeout的時間等等);而且每個Sub-Task也要擁有不同的fallback或Error Handling。

Sample Code:

Task.callInBackground(new Callable<List<User>>() {
     @Override public List<User> call() {
         return queryListFromNetwork();
     }
}, NETWORK_EXECUTOR)
.onSuccess(Continuation<List<User>, List<Image>>() {
    @Override public List<List<Image>> then(Task<List<User>> task) {
        List<Image> list = new ArrayList<Image>();
        for (User user : task.getResult()) {
             list.add(loadImage(user));
        }
        return list;
    }
}, NETWORK_EXECUTOR)
.onSuccess(Continuation<List<Image>, Integer>() {
    @Override public Integer then(Task<List< Image >> task) {
        int count = 0;
        for (Image image : task.getResult()) {
             saveToStorage(image);
             count ++;
        }
        return count;
    }
}, STORAGE_EXECUTOR)
.continueWith(Continuation<Integer, Void>() {
    @Override public void then(Task<Integer> task) {
        if (task.isFault()) {
            task.getError();
        }
        if (task.isComplete()) {
            // show success message
        }
    }
}, UI_EXECUTOR);


Q. 那是否支援等待多個Task?
A. 當然,可以使用Task.whenAll()

Sample Code

List<Task> tasks = new ArrayList<Task>();
for (int i = 0 ; i< 100 ; i ++) {
    tasks.add(Task.callInBackground(new Callable<Void>() {
      @Override public void call() {
         downloadFile();
         return null;
      }
    }));
}
Task.whenAll(tasks).continueWith(Continuation<Void, Void>() {
    @Override public void then(Task<Void> task) {
        if (task.isFault()) {
            task.getError();
        }
        if (task.isComplete()) {
            // show success message
        }
    }
}, UI_EXECUTOR);


Q 看起來那麼完美,那目前是否有些缺點?
A 當然,畢竟是v1.0.0,目前看到比較缺乏的功能:1. 無法cancel Task。2. 當使用whenAll的時候無法取得所有Sub-Task的Result。



如果還有什麼使用上或者解說上不是那麼清楚的地方請與我聯繫討論。



2014年2月17日 星期一

Kindle Fire's soft-key bar

   近APP要重新上架到Amazon的App Store,在Review時被測出一個Issue;就是在Full-Screen的Activity當置底(BOTTOM|CENTER)的DialogFragment彈出時,會被Kindle Fire的Soft-key Bar給擋住。

    原因在於Kindle Fire的Soft-key不是固定占用系統的高度,所以在Full Screen時,如果彈出的Dialog可以支援Back Key來取消的時候,它就會雞婆的把Soft-key用Overlay的方式跳出,就巧妙地擋住部分的Dialog。

原本的解法是判斷手機是否為Kindle Fire,然後決定要不要加上一個神奇的Margin-Bottom,但後來跟同事Pair-Program後,發現到DialogFragment加道Window時,並沒有繼承現在Activity的屬性(也就是全螢幕),所以才會做出如此蠢事。

最後我們捨棄的Magic Margin,而是強制將DialogFragment設成全螢幕的模式,如此該死的Soft-Key Bar就不會莫名其妙的彈跳出來。

Sample Code :

dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

2014年2月9日 星期日

您的Service能夠活多久?

   晚整理以前信件時,發現某個資料夾裡放滿所有註冊網站服務的認證信,大約都是在2007到2009年所註冊,悲慘的是超過一半的網站都已經GG,以下條列他們以前的服務名稱以及網域。

  • http://www.iloveeasy.com/
  • CrazyVote
  • http://www.pala88.com/
  • http://www.bday2all.com/
  • 搜股網
  • http://www.showgood.tw/
  • http://my98.98play.com.tw/
  • http://www.badongo.com/
  • 地圖日記
  • HEMiDEMi
  • http://www.ppolis.com
  • 意慾蔓延
  • joost
  • http://www.postreach.com
  • http://tw.blogdeco.jp/
  • http://www.mybloglog.com/buzz/community/mybloglog/
  • http://dob.tnc.edu.tw/ 
  • http://slide.com/

有趣的地方在於,上列網站幾乎都在認證信內貼上明文的密碼(我的密碼沒加密搜集了所有密碼沒加密的網站)。