<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 35  文章 - 21  trackbacks - 0
    <2010年2月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28123456
    78910111213

    常用鏈接

    留言簿

    隨筆分類

    隨筆檔案

    文章分類

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    1 Launch Keychain Access from your local Mac and from the login keychain, filter by the Certificates category. You will see an expandable option called “Apple Development Push Services”
    2 Right click on “Apple Development Push Services” > Export “Apple Development Push Services ID123″. Save this as apns-dev-cert.p12 file somewhere you can access it. There is no need to enter a password.
    3 The next command generates the cert in Mac’s Terminal for PEM format (Privacy Enhanced Mail Security Certificate):
    openssl pkcs12 -in apns-dev-cert.p12 -out apns-dev-cert.pem -nodes -clcerts
    posted @ 2012-05-29 11:07 lincode 閱讀(732) | 評論 (0)編輯 收藏

    這個 bug 在 xcode 4.3 以下會出現,4.3 以后已經修正了。
    解決方法為:找到 target 的圖標,更改其 Other Linker Flags 為: -all_load 或 -force_load
    -force_load,后跟隨一個文件位置,可以更精確地加載所需文件。
     
    蘋果的解釋為 : http://developer.apple.com/library/mac/#qa/qa1490/_index.html

    簡單點說就是,Objective-C 的動態(tài)特性使得需要,為鏈接器添加一個標簽(設置 Other Linker Flags 為 -ObjC)來解決通過 Category 向類添加方法的問題。
    但這個標簽 -ObjC 在 64 位 和 iOS 中有問題,需要使用 -all_load 或 -force_load。

    總結如下:
    如果,第三庫中沒有 category,Other Linker Flags 無需設置
    如果,第三方庫中有 category,需要設置為 -ObjC
    如果,某些 Xcode 版本中,出現問題,修改設置為 -all_load
    posted @ 2012-04-23 14:56 lincode 閱讀(1814) | 評論 (0)編輯 收藏
    獲得 Crash Report:
    1 itunesConnect 的后臺會提供一個 Crash report 表;
    2 把一臺打開了開發(fā)模式的機器接入 Mac,Xcode 的 Organizer 中能查看這臺設備的 Crash Report;
    3 若使用了 Umeng.com, Bugsense.com 之類的工具。

    閱讀 Crash Report:
    這之前需要一個名為 AppName.app.dSYM 的文件。Xcode 中,Archive 一個項目之后,可以在 Organizer 的 Archives 分頁中,找到所有項目的 Archvie 文件。
    右鍵點擊一個, Show Package Content,就能看到一個類似 AppName-3-19-12.app.PM.xcarchive  的文件,show in finder 這個文件,就能找到 .dSYM 文件。

    在 Ternimal 中執(zhí)行,若是 來自于 iphone 3G 的機器,就需要使用 armv6 代替 armv7.

     atos -o AppName.app.dSYM/Contents/Resources/DWARF/AppName  -arch armv7 0x0000b82

    這樣就能看到,地址對應的類,函數,代碼行數。這個命令只能解析出客戶代碼的位置。若是錯誤堆棧中的系統(tǒng)調用,是無法翻譯出來的。
    posted @ 2012-03-18 13:56 lincode 閱讀(1001) | 評論 (0)編輯 收藏
    Apple 提供了一個地址方向解析的服務 MKReverseGeocoder,上傳一個經緯度,返回一個詳細的地理位置信息。但這個服務在中國不太穩(wěn)定,時常不可用。
    Google map 也提供了一個類似的服務,是訪問一個 google map 的 api,這里試圖封裝了 google map 的服務。使使用 apple 和 google 的服務的接口基本一致,替換起來很容易。Google map 的這個服務在中國的狀態(tài)比 apple 稍微好一些,但也有不穩(wěn)定的時候。我猜想,apple 也許是使用 google 的服務封裝了自己的 MKReverseGeocoder。若是如此,這里的嘗試也就沒有什么意義了。

    DOUHttpRequest 是對 ASIHTTPRequest 的一個簡單封裝。這些代碼可以 繼承自 MKReverseGeocoder。這樣,使用方法就和 MKReverseGeocoder 一樣了。

    static NSString* kGeoServerUrl = @"http://maps.google.com/maps/api/geocode/json?latlng=%f,%f&sensor=true&language=en";
    static NSString* kLatitudeUserInfoKey = @"latitudeUserInfoKey";
    static NSString* kLongitudeUserInfoKey = @"longitudeUserInfoKey";

    //
    // It's tje solution for replacing MKReverseGeocoder that has problem in China.
    //
    - (void)startedReverseGeoderWithLatitude:(double)latitude longitude:(double)longitude {
      NSString *url = [NSString stringWithFormat:kGeoServerUrl, latitude, longitude];
      DOUHttpRequest *req = [DOUHttpRequest requestWithURL:[NSURL URLWithString:url] target:self];
      
      NSNumber *lat = [NSNumber numberWithDouble:latitude];
      NSNumber *lon = [NSNumber numberWithDouble:longitude];
      req.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:lat, kLatitudeUserInfoKey, lon, kLongitudeUserInfoKey, nil];
      
      DOUService *service = [DOUService sharedInstance];  
      [service addRequest:req];
    }


    - (NSDictionary *)addressDictionary:(NSObject *)obj {
      
      NSArray* ary = nil;
      if (IS_INSTANCE_OF(obj, NSDictionary)) {
        NSObject* data = [(NSDictionary*)obj objectForKey:@"results"];
        if (IS_INSTANCE_OF(data, NSArray)) {
          ary = (NSArray*)data;
          NSDictionary *dic = [ary objectAtIndex:0];
          
          NSArray *addressComps = [dic objectForKey:@"address_components"];
          
          //NSString *streetNumber = @"";
          NSString *route = @"";
          NSString *locality = @"";
          NSString *country = @"";
          for (NSDictionary *comp in addressComps) {
            NSArray *types = [comp objectForKey:@"types"];
            NSString *type = [types objectAtIndex:0];
            
    //        if ([type isEqualToString:@"street_number"]) {
    //          streetNumber = [comp objectForKey:@"long_name"];
    //        }
            
            if ([type isEqualToString:@"route"]) {
              route = [comp objectForKey:@"long_name"];
            }
            
            if ([type isEqualToString:@"locality"]) {
              locality = [comp objectForKey:@"long_name"];
            }
            
            if ([type isEqualToString:@"country"]) {
              country = [comp objectForKey:@"long_name"];
            }        
          }
          
          NSDictionary *addressDic = [NSDictionary dictionaryWithObjectsAndKeys:route, kABPersonAddressStreetKey,
                                      locality, kABPersonAddressCityKey,                                        
                                      country, kABPersonAddressCountryKey, nil];
          return addressDic;
        }
      }
      return nil;
    }


    - (void)requestFinished:(DOUHttpRequest *)req {
      NSError *error = [req error];
      if (!error) {
        DebugLog(@"str:%@", [req responseString]);
        
        NSObject *obj = [[req responseString] JSONValue];
        NSDictionary *addressDic = [self addressDictionary:obj];
        
        CLLocationCoordinate2D coordinate;
        coordinate.latitude = [[req.userInfo objectForKey:kLatitudeUserInfoKey] doubleValue];
        coordinate.longitude = [[req.userInfo objectForKey:kLongitudeUserInfoKey] doubleValue]; 
        MKPlacemark *placemark = [[[MKPlacemark alloc] initWithCoordinate:coordinate 
                                                       addressDictionary:addressDic] autorelease];
        [self reverseGeocoder:nil didFindPlacemark:placemark];
      }
    }

    - (void)requestFailed:(DOUHttpRequest *)req { 
      [self reverseGeocoder:nil didFailWithError:[req error]];
    }


    #pragma mark - MKReverseGeocoderDelegate

    static NSString * const AppleLanguagesKey = @"AppleLanguages";

    - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {

      NSArray *array = [[NSUserDefaults standardUserDefaults] objectForKey:AppleLanguagesKey];
      NSString *currentLanguage = [array objectAtIndex:0];
      
      // set current language as english
      [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"zh-Hans", nil] 
                                                forKey:AppleLanguagesKey];
      NSString *local = [placemark.locality lowercaseString];
     
      [AppContext sharedInstance].currentCityUid = local;
      
      // reset current language
      [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:currentLanguage, nil] 
                                                forKey:AppleLanguagesKey];
    }

    - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
      TraceLog(@"reverseGeocoder :%@", [error localizedDescription]);  
    }
    posted @ 2012-01-12 21:27 lincode 閱讀(1367) | 評論 (0)編輯 收藏

    定義

    OAuth(開放授權)是一個開放標準,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯系人列表),而無需將用戶名和密碼提供給第三方應用。

    OAuth允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每一個令牌授權一個特定的網站(例如,視頻編輯網站)在特定的時段(例如,接下來的2小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth允許用戶授權第三方網站訪問他們存儲在另外的服務提供者上的信息,而不需要分享他們的訪問許可或他們數據的所有內容。



    認證和授權過程


    在認證和授權的過程中涉及的三方包括:
    • 服務提供方,用戶使用服務提供方來存儲受保護的資源,如照片,視頻,聯系人列表。
    • 用戶,存放在服務提供方的受保護的資源的擁有者。
    • 客戶端,要訪問服務提供方資源的第三方應用,通常是網站,如提供照片打印服務的網站。在認證過程之前,客戶端要向服務提供者申請客戶端標識。

    使用OAuth進行認證和授權的過程如下所示:

    1. 用戶訪問客戶端的網站,想操作用戶存放在服務提供方的資源。
    2. 客戶端服務提供方請求一個臨時令牌。
    3. 服務提供方驗證客戶端的身份后,授予一個臨時令牌。
    4. 客戶端獲得臨時令牌后,將用戶引導至服務提供方的授權頁面請求用戶授權。在這個過程中將臨時令牌和客戶端的回調連接發(fā)送給服務提供方
    5. 用戶服務提供方的網頁上輸入用戶名和密碼,然后授權該客戶端訪問所請求的資源。
    6. 授權成功后,服務提供方引導用戶返回客戶端的網頁。
    7. 客戶端根據臨時令牌從服務提供方那里獲取訪問令牌。
    8. 服務提供方根據臨時令牌和用戶的授權情況授予客戶端訪問令牌。
    9. 客戶端使用獲取的訪問令牌訪問存放在服務提供方上的受保護的資源。


    OAuth 2.0

    OAuth 2.0是OAuth協議的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0關注客戶端開發(fā)者的簡易性,同時為Web應用,桌面應用和手機,和起居室設備提供專門的認證流程。規(guī)范還在IETF OAuth工作組的開發(fā)中 ,按照Eran Hammer-Lahav的說法,OAuth將于2010年末完成。

    Facebook的新的Graph API只支持OAuth 2.0,Google在2011年3月亦宣佈Google API對OAuth 2.0的支援。

    posted @ 2011-10-27 18:15 lincode 閱讀(323) | 評論 (0)編輯 收藏

    名稱

    REST,即Representational State Transfer的縮寫。我對這個詞組的翻譯是"表現層狀態(tài)轉化"。

    如果一個架構符合REST原則,就稱它為RESTful架構。

    要理解RESTful架構,最好的方法就是去理解Representational State Transfer這個詞組到底是什么意思,它的每一個詞代表了什么涵義。如果你把這個名稱搞懂了,也就不難體會REST是一種什么樣的設計。

    資源(Resources)

    REST的名稱"表現層狀態(tài)轉化"中,省略了主語。"表現層"其實指的是"資源"(Resources)的"表現層"。

    所謂"資源",就是網絡上的一個實體,或者說是網絡上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。你可以用一個URI(統(tǒng)一資源定位符)指向它,每種資源對應一個特定的URI。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地址或獨一無二的識別符。

    所謂"上網",就是與互聯網上一系列的"資源"互動,調用它的URI。

    表現層(Representation)

    "資源"是一種信息實體,它可以有多種外在表現形式。我們把"資源"具體呈現出來的形式,叫做它的"表現層"(Representation)。

    比如,文本可以用txt格式表現,也可以用HTML格式、XML格式、JSON格式表現,甚至可以采用二進制格式;圖片可以用JPG格式表現,也可以用PNG格式表現。

    URI只代表資源的實體,不代表它的形式。嚴格地說,有些網址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬于"表現層"范疇,而URI應該只代表"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段才是對"表現層"的描述。

    狀態(tài)轉化(State Transfer)

    訪問一個網站,就代表了客戶端和服務器的一個互動過程。在這個過程中,勢必涉及到數據和狀態(tài)的變化。

    互聯網通信協議HTTP協議,是一個無狀態(tài)協議。這意味著,所有的狀態(tài)都保存在服務器端。因此,如果客戶端想要操作服務器,必須通過某種手段,讓服務器端發(fā)生"狀態(tài)轉化"(State Transfer)。而這種轉化是建立在表現層之上的,所以就是"表現層狀態(tài)轉化"。

    客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源。

    綜述

    綜合上面的解釋,我們總結一下什么是RESTful架構:

      (1)每一個URI代表一種資源;

      (2)客戶端和服務器之間,傳遞這種資源的某種表現層;

      (3)客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現"表現層狀態(tài)轉化"。

    誤區(qū)

    RESTful架構有一些典型的設計誤區(qū)。

    最常見的一種設計錯誤,就是URI包含動詞。因為"資源"表示一種實體,所以應該是名詞,URI不應該有動詞,動詞應該放在HTTP協議中。

    舉例來說,某個URI是/posts/show/1,其中show是動詞,這個URI就設計錯了,正確的寫法應該是/posts/1,然后用GET方法表示show。

    如果某些動作是HTTP動詞表示不了的,你就應該把動作做成一種資源。比如網上匯款,從賬戶1向賬戶2匯款500元,錯誤的URI是:

      POST /accounts/1/transfer/500/to/2

    正確的寫法是把動詞transfer改成名詞transaction,資源不能是動詞,但是可以是一種服務:

      POST /transaction HTTP/1.1
      Host: 127.0.0.1
      
      from=1&to=2&amount=500.00

    另一個設計誤區(qū),就是在URI中加入版本號

      http://www.example.com/app/1.0/foo

      http://www.example.com/app/1.1/foo

      http://www.example.com/app/2.0/foo

    因為不同的版本,可以理解成同一種資源的不同表現形式,所以應該采用同一個URI。版本號可以在HTTP請求頭信息的Accept字段中進行區(qū)分(參見Versioning REST Services):

      Accept: vnd.example-com.foo+json; version=1.0

      Accept: vnd.example-com.foo+json; version=1.1

      Accept: vnd.example-com.foo+json; version=2.0


    原帖:http://www.ruanyifeng.com/blog/2011/09/restful.html
    posted @ 2011-10-27 18:02 lincode 閱讀(302) | 評論 (0)編輯 收藏

    PhoneGap 是一個移動開發(fā)框架。通過 PhoneGap,開發(fā)者可以使用 JavaScript 調用手機的原生功能,例如,獲取經緯度,讓手機振動等。
    主頁 http://www.phonegap.com/ 。
    源碼 https://github.com/phonegap/phonegap-android 。

    PhoneGap 在早期,應該是使用 WebView 的 addJavaScriptInterface 方法,來為 JS 提供調用原生功能可能。addJavaScriptInterface ,可以將一個 Java 對象綁定到一個 JS 對象。是的,JS對象可以調用 Java方法。但在 PhoneGap 1.0.0 這個版本中,PhoneGap 改變了方法。

    以振動功能為例,我們可以看一下程序調用的流程:

    1 在 JS 中,啟動命令

    main.js / navigator.notification.vibrate(0);

    notification.js / Notification.vibrate.vibrate 中執(zhí)行了 PhoneGap.exec(null, null, "Notification", "vibrate", [mills]);

    phonegap.js / PhoneGap.exc 中執(zhí)行了 var r = prompt(PhoneGap.stringify(args), "gap:"+PhoneGap.stringify([service, action, callbackId, true]));

    這時,WebView 就會企圖彈出一個窗口。這時使用 android 提供的 WebChromeClient 的 API 就可以截獲 WebView 的這個動作 。

    2 JAVA 中,處理命令
    WebView 的 WebChromClient 實現了下面這個函數:

    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)

    在 onJsPrompt 中執(zhí)行了 String r = pluginManager.exec(service, action, callbackId, message, async);

    PlugManager 會根據收到參數,將命令分發(fā)給特定的 Plugin。這個例子中,接收的 plugin 是:Notification。
    落實到 Notification 的 exec 函數:會執(zhí)行這一行: this.vibrate(args.getLong(0));

    振動的實現為:

     

     public void vibrate(long time){
            
    // Start the vibration, 0 defaults to half a second.
            if (time == 0) {
    time 
    = 500;
    }
            Vibrator vibrator 
    = (Vibrator) this.ctx.getSystemService(Context.VIBRATOR_SERVICE);
            vibrator.vibrate(time);
    }

     


    3 Java 處理完后的數據,需要給 JS 一個反饋:
    這里 PhoneGap 使用了一個在客戶端本地實現的 XHRServer,具體到代碼中就是一個JAVA 類 CallbackServer。

    分兩個部分介紹其行為:
    本地 XHRServer,
    思想是,后臺每執(zhí)行完一個命令,都會將結果存在 CallbackServer 中的一個鏈表中,具體為CallbackServr的 private LinkedList<String> javascript;
    這個結果其實是一段字符串表示的 JS 函數調用。例如檢測網絡調用的結果為:PhoneGap.callbackSuccess('Network Status1',{status:1,message:"wifi",keepCallback:true});
     XHRServer 的行為很簡單,只要有請求來,就把鏈表中的最先進來的提出來,返回給客戶端。沒有請求來,則 10秒鐘返回一個空的回復,以維持XHRServer。
    Webview 作為客戶端:
    在 WebView 中,會有一個輪詢機制,這可以參考 PhoneGap.JSCallack 和 PhoneGap.JSCallbackPolling 兩個函數來訪問 XHRServer。XHRServer,返回的結果就是 WebView 需要調用的 JS 函數。 在 JS 中,eval() 函數,將返回的結果變?yōu)橐粋€可以執(zhí)行的對象,在 Webview 中執(zhí)行,可以認為這即是回調函數 Callback。這也是為什么 PhoneGap 為何命名 XHRServer 為 CallbackServer 的原因。

    posted @ 2011-09-20 10:20 lincode 閱讀(3742) | 評論 (1)編輯 收藏
    dip: device independent pixels(設備獨立像素)。不同設備有不同的顯示效果,這個和設備硬件有關,一般我們?yōu)榱酥С諻VGA、HVGA和QVGA 推薦使用這個,不依賴像素。 

    dp:(與密度無關的像素)一種基于屏幕密度的抽象單位。在每英寸160點的顯示器上,1dp = 1px。 

    px: pixels(像素). 不同設備顯示效果相同,一般我們HVGA代表320x480像素,這個用的比較多。 

    pt: point(磅),是一個標準的長度單位,1pt=1/72英寸,用于印刷業(yè),非常簡單易用; 

    sp: scaled pixels(放大像素). 主要用于字體顯示best for textsize。 
    posted @ 2011-09-16 17:58 lincode 閱讀(722) | 評論 (1)編輯 收藏

    android 中自定義的對象序列化的問題有兩個選擇一個是Parcelable,另外一個是Serializable。

    一 序列化原因:

    1.永久性保存對象,保存對象的字節(jié)序列到本地文件中;
    2.通過序列化對象在網絡中傳遞對象;
    3.通過序列化在進程間傳遞對象。 

    二 至于選取哪種可參考下面的原則:

    1.在使用內存的時候,Parcelable 類比Serializable性能高,所以推薦使用Parcelable類。
    2.Serializable在序列化的時候會產生大量的臨時變量,從而引起頻繁的GC。
    3.Parcelable不能使用在要將數據存儲在磁盤上的情況,因為Parcelable不能很好的保證數據的持續(xù)性在外界有變化的情況下。盡管Serializable效率低點, 也不提倡用,但在這種情況下,還是建議你用Serializable 。


    實現:
    1 Serializable 的實現,只需要繼承  implements Serializable 即可。這只是給對象打了一個標記,系統(tǒng)會自動將其序列化。

    2 Parcelabel 的實現,需要在類中添加一個靜態(tài)成員變量 CREATOR,這個變量需要繼承 Parcelable.Creator 接口。
    public class MyParcelable implements Parcelable {
         
    private int mData;

         
    public int describeContents() {
             
    return 0;
         }

         
    public void writeToParcel(Parcel out, int flags) {
             out.writeInt(mData);
         }

         
    public static final Parcelable.Creator<MyParcelable> CREATOR
                 
    = new Parcelable.Creator<MyParcelable>() {
             
    public MyParcelable createFromParcel(Parcel in) {
                 
    return new MyParcelable(in);
             }

             
    public MyParcelable[] newArray(int size) {
                 
    return new MyParcelable[size];
             }
         };
         
         
    private MyParcelable(Parcel in) {
             mData 
    = in.readInt();
         }
     }

     
    posted @ 2011-09-16 16:16 lincode 閱讀(22137) | 評論 (0)編輯 收藏
    生命周期
    Android 系統(tǒng)在Activity 生命周期中加入一些鉤子,我們可以在這些系統(tǒng)預留的鉤子中做一些事情。
    例舉了 7 個常用的鉤子:
    protected void onCreate(Bundle savedInstanceState)
    protected void onStart()
    protected void onResume()
    protected void onPause()
    protected void onStop()
    protected void onRestart()
    protected void onDestroy()

    簡要說明:
    onCreate(Bundle savedInstanceState):創(chuàng)建activity時調用。設置在該方法中,還以Bundle中可以提出用于創(chuàng)建該 Activity 所需的信息。
    onStart():activity變?yōu)樵谄聊簧蠈τ脩艨梢姇r,即獲得焦點時,會調用。
    onResume():activity開始與用戶交互時調用(無論是啟動還是重新啟動一個活動,該方法總是被調用的)。
    onPause():activity被暫停或收回cpu和其他資源時調用,該方法用于保存活動狀態(tài)的。。
    onStop():activity被停止并轉為不可見階段及后續(xù)的生命周期事件時,即失去焦點時調用。
    onRestart():重新啟動activity時調用。該活動仍在棧中,而不是啟動新的活動。
    onDestroy():activity被完全從系統(tǒng)內存中移除時調用,該方法被調用可能是因為有人直接調用 finish()方法 或者系統(tǒng)決定停止該活動以釋放資源。

    橫豎屏切換

    1 切換到橫屏
    onSaveInstanceState
    onPause
    onStop
    onDestroy
    onCreate
    onStart
    onRestoreInstanceState
    onResume

    2 切換到豎屏,銷毀了兩次
    onSaveInstanceState
    onPause
    onStop
    onDestroyonCreate
    onStart
    onRestoreInstanceState
    onResume
    onSaveInstanceState
    onPause
    onStop
    onDestroy
    onCreate
    onStart
    onRestoreInstanceState
    onResume

    3 修改AndroidManifest.xml,把該Activity添加 android:configChanges="orientation",切橫屏,只銷毀一次。

    onSaveInstanceState
    onPause
    onStop
    onDestroy
    onCreate
    onStart
    onRestoreInstanceState
    onResume

    再切回豎屏,發(fā)現不會再打印相同信息,但多打印了一行onConfigChanged

    onSaveInstanceState
    onPause
    onStop
    onDestroy
    onCreate
    onStart
    onRestoreInstanceState
    onResume
    onConfigurationChanged

    5 更改 android:configChanges="orientation" 改成 android:configChanges="orientation|keyboardHidden",切橫屏,就只打印onConfigChanged

    onConfigurationChanged

    6 切回豎屏

    onConfigurationChanged
    onConfigurationChanged

    總結:

    1、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執(zhí)行一次,切豎屏時會執(zhí)行兩次

    2、設置Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執(zhí)行一次

    3、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命周期,只會執(zhí)行onConfigurationChanged方法





    posted @ 2011-09-16 10:32 lincode 閱讀(3371) | 評論 (1)編輯 收藏
    Python 的代碼風格由 PEP 8 描述。這個文檔描述了 Python 編程風格的方方面面。在遵守這個文檔的條件下,不同程序員編寫的 Python 代碼可以保持最大程度的相似風格。這樣就易于閱讀,易于在程序員之間交流。


    1 變量

    常量 : 大寫加下劃線
    USER_CONSTANT
    對于不會發(fā)生改變的全局變量,使用大寫加下劃線。

    私有變量
    : 小寫和一個前導下劃線
    _private_value
    Python 中不存在私有變量一說,若是遇到需要保護的變量,使用小寫和一個前導下劃線。但這只是程序員之間的一個約定,用于警告說明這是一個私有變量,外部類不要去訪問它。但實際上,外部類還是可以訪問到這個變量。

    內置變量 : 小寫,兩個前導下劃線和兩個后置下劃線
    __class__
    兩個前導下劃線會導致變量在解釋期間被更名。這是為了避免內置變量和其他變量產生沖突。用戶定義的變量要嚴格避免這種風格。以免導致混亂。


    2 函數和方法

    總體而言應該使用,小寫和下劃線。但有些比較老的庫使用的是混合大小寫,即首單詞小寫,之后每個單詞第一個字母大寫,其余小寫。但現在,小寫和下劃線已成為規(guī)范。

    私有方法 : 小寫和一個前導下劃線
    def _secrete(self):
        
    print "don't test me."

    這里和私有變量一樣,并不是真正的私有訪問權限。同時也應該注意一般函數不要使用兩個前導下劃線(當遇到兩個前導下劃線時,Python 的名稱改編特性將發(fā)揮作用)。特殊函數后面會提及。

    特殊方法 : 小寫和兩個前導下劃線,兩個后置下劃線

    def __add__(self, other):
        
    return int.__add__(other)

    這種風格只應用于特殊函數,比如操作符重載等。

    函數參數 : 小寫和下劃線,缺省值等號兩邊無空格

    def connect(self, user=None):
        self._user 
    = user



    3 類

    類總是使用駝峰格式命名,即所有單詞首字母大寫其余字母小寫。類名應該簡明,精確,并足以從中理解類所完成的工作。常見的一個方法是使用表示其類型或者特性的后綴,例如:
    SQLEngine
    MimeTypes

    對于基類而言,可以使用一個 Base 或者 Abstract 前綴
    BaseCookie
    AbstractGroup

    class UserProfile(object):
        
    def __init__(self, profile):
            
    return self._profile = profile

        
    def profile(self):
            
    return self._profile



    4 模塊和包

    除特殊模塊 __init__ 之外,模塊名稱都使用不帶下劃線的小寫字母。
    若是它們實現一個協議,那么通常使用lib為后綴,例如:
    import smtplib

    import os
    import sys



    5 關于參數

    5.1 不要用斷言來實現靜態(tài)類型檢測
    斷言可以用于檢查參數,但不應僅僅是進行靜態(tài)類型檢測。 Python 是動態(tài)類型語言,靜態(tài)類型檢測違背了其設計思想。斷言應該用于避免函數不被毫無意義的調用。

    5.2 不要濫用 *args 和 **kwargs
    *args 和 **kwargs 參數可能會破壞函數的健壯性。它們使簽名變得模糊,而且代碼常常開始在不應該的地方構建小的參數解析器。


    6 其他

    6.1 使用 has 或 is 前綴命名布爾元素

    is_connect = True
    has_member 
    = False


    6.2 用復數形式命名序列

    members = ['user_1''user_2']


    6.3 用顯式名稱命名字典

    person_address = {'user_1':'10 road WD''user_2' : '20 street huafu'}


    6.4 避免通用名稱
    諸如 list, dict, sequence 或者 element 這樣的名稱應該避免。

    6.5 避免現有名稱
    諸如 os, sys 這種系統(tǒng)已經存在的名稱應該避免。


    7 一些數字
    一行列數 : PEP 8 規(guī)定為 79 列,這有些苛刻了。根據自己的情況,比如不要超過滿屏時編輯器的顯示列數。這樣就可以在不動水平游標的情況下,方便的查看代碼。

    一個函數 : 不要超過 30 行代碼, 即可顯示在一個屏幕類,可以不使用垂直游標即可看到整個函數。
    一個類 : 不要超過 200 行代碼,不要有超過 10 個方法。
    一個模塊 不要超過 500 行


    8 驗證腳本

    可以安裝一個 pep8 腳本用于驗證你的代碼風格是否符合 PEP8。

    >>easy_install pep8

    >>pep8 -r --ignoire E501 Test.py

    這個命令行的意思是,重復打出錯誤,并且忽略 501 錯誤(代碼超過 79 行)。

    posted @ 2011-02-02 00:45 lincode 閱讀(9323) | 評論 (0)編輯 收藏
    Emacs 不僅僅是一個文本編輯器,它還可用于文件管理。使用 Emacs 作為文件管理工具的話,也解決了跨平臺問題,這樣在不同平臺下,你都可以使用一套工具來管理文件。

    1 基本命令
    Ctrl + x  d  : 打開文件管理視圖,在文件管理視圖中支持的操作如下表:
    鍵值 效果    
    Enter 打開文件
    a 打開文件并關閉文件管理視圖
    打開文件,但是在一個新建視圖中打開
    關閉文件管理視圖
    C(大寫) 復制文件
    R(大寫) 重命名文件
    D(大寫) 刪除文件


    2 基于文件集合的命令
    這主要是使一條命令作用于幾個文件。方法是標記你要操作的文件。
    基本命令為 m

    鍵值  效果    
    m 標記文件
    u 去掉標記
    U 標記所有文件
    t 反向所以文件
    % m 基于正則表達式,標記文件


    3 其他相關命令
    在文件管理視圖中還可以做到:
    鍵值 效果    
    g 刷新文件夾
    ^ 返回上級目錄
    + 創(chuàng)建一個文件夾
    壓縮或解壓文件


    posted @ 2011-02-01 18:14 lincode 閱讀(1070) | 評論 (0)編輯 收藏

    我使用的是 goddady 的 VPS。家里使用 mac 。所以直接在 terminal 中使用 ssh 連接服務器即可。

    > ssh 189.129.1.12 -l username
    敲入密碼,進入服務器。

    > su
    敲入密碼,進入根用戶。

    > cd /etc/ngnix/
    進入 ngnix 配置文件目錄,進入 conf.d 目錄

    > vim ghs.conf
    建立一個 配置文件

    一個范例:

    upstream ghs {
        ip_hash;
        server ghs.google.com;
        server 72.14.203.121;
        server 72.14.207.121;
        server 74.125.43.121;
        server 74.125.47.121;
        server 74.125.53.121;
        server 74.125.77.121;
        server 74.125.93.121;
        server 74.125.95.121;
        server 74.125.113.121;
        server 216.239.32.21;
        server 216.239.34.21;
        server 216.239.36.21;
        server 216.239.38.21;
    }

    server {
        listen       80;
        server_name  ghs.myhosts.com www.test.com;
        access_log   /data/logs/ghs_proxyaccess.log;

        location / {
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_pass http://ghs;
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect false;
        }

    }


    >/etc/init.d/ngnix start

    啟動 nginx

    在本機的瀏覽器中敲入反向代理 server 的 ip,能看到 ngnix 的藍色的界面,這驗證了 ngnix 啟動正常

    > ping ghs.myhosts.com
    應該指向反向代理 server 的 ip

    首先將你的域名例如,www.tests.com  綁定到 google app engine 的你的目標 application 上
    然后,在你的域名服務提供商那里,添加一個 www.tests.com 指向 ghs.myhosts.com 的 CNAME 即可。

    posted @ 2010-12-15 07:12 lincode 閱讀(503) | 評論 (0)編輯 收藏

      transient:

      java有個特點就是序列化,簡單地來說就是可以將這個類存儲在物理空間(當然還是以文件的形式存在),那么當你從本地還原這個文件時,你可以將它轉換為它本身。這可以極大地方便網絡上的一些操作,但同時,因為涉及到安全問題,所以并不希望把類里面所有的東西都能存儲(因為那樣,別人可以通過序列化知道類里面的內容),那么我們就可以用上transient這個關鍵字,它的意思是臨時的,即不會隨類一起序列化到本地,所以當還原后,這個關鍵字定義的變量也就不再存在。

      volatile:

      Volatile 修飾的成員變量在每次被線程訪問時,都強迫從共享內存中重讀該成員變量的值。而且,當成員變量發(fā)生變化時,強迫線程將變化值回寫到共享內存。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。

      Java 語言規(guī)范中指出:為了獲得最佳速度,允許線程保存共享成員變量的私有拷貝,而且只當線程進入或者離開同步代碼塊時才與共享成員變量的原始值對比。

      這樣當多個線程同時與某個對象交互時,就必須要注意到要讓線程及時的得到共享成員變量的變化。

      而volatile關鍵字就是提示VM:對于這個成員變量不能保存它的私有拷貝,而應直接與共享成員變量交互。

      使用建議:在兩個或者更多的線程訪問的成員變量上使用volatile。當要訪問的變量已在synchronized代碼塊中,或者為常量時,不必使用。

      由于使用volatile屏蔽掉了VM中必要的代碼優(yōu)化,所以在效率上比較低,因此一定在必要時才使用此關鍵字。

    posted @ 2010-06-14 23:03 lincode 閱讀(227) | 評論 (0)編輯 收藏

    一 基本概念
    單例模式是一種為類 提供唯一實例的設計模式。單例模式的目的是為了控制對象的創(chuàng)建,它可以限制創(chuàng)建的數目為一,但在情況改變的時候,也允許靈活地創(chuàng)建更多的對象。因為只有一個實例,所以也只有一套實例的類變量的拷貝,這很像 static 變量。

    在 JAVA 中,單例模式不應該被當作一種實現全局變量的方法。更多的,如同工廠模式,單例模式允許你通過 確認某些先決條件是否滿足 或者 以 lazily 方式按需創(chuàng)建的方式 來封裝和控制創(chuàng)建過程。

    二 編程實現
    1 饑餓模式 Eager Singleton

    public class MySingleton {
        
    private static MySingleton fInstance = new MySingleton();
        
        
    private MySingleton(){
            
    // Construct object 
        }


        
    public static MySingleton getInstance(){
            reutnr fInstance;
        }


    }

    2 懶漢模式 Lazy Singleton

    public class MySingleton {
        
    private static MySingleton fInstance;
        
        
    private MySingleton(){
            
    // construct object
        }

        
        
    public static synchronized MySingleton getInstance(){
            
    if (fInstance == null){
                fInstance 
    = new MySingleton();
            }

            
    return fInstance;
        }


    }

    由于只有一個私有構造器,所以單例類是無法被集成的。基于這一點,單例模式并不是一個面向對象模式,僅僅是一個基于對象的模式。

    3 饑餓模式基本沒有問題,懶漢模式則容易出現一些錯誤的編程方法
    1)
    // error, no synchronization on method 
    public static MySingleton getInstance() 
     
    if (fInstance==null
         fInstance 
    = new MySingleton(); 
     }
     

     
    return fInstance; 
    }

    2)
    // Also an error, synchronization does not prevent 
    // two calls of constructor. 
    public static MySingleton getInstance() 
     
    if (fInstance==null
       
    synchronized (MySingleton.class
          fInstance 
    = new MySingleton(); 
       }
     
     }
     
     
    return fInstance; 
    }
     

    3) Double-checked locking 不要使用

    public static MySingleton getInstance(){
        
    if (fInstance == null ){
            
    synchronized (MySingleton.class{
                
    if(fInstance == null){
                    fInstance 
    = new MySingleton();
                }

            }

        }

    }

    為了避免每次調用 getInstance方法是抓取同步鎖的消耗,有人發(fā)明了 Double-checked locking 。但不要使用,因為這樣的代碼將無法在編譯器優(yōu)化和多處理器共享內存的情況下工作。若想詳細了解,附錄中有對此做詳細描述的鏈接。

    三 總結

    1 單例模式不應被濫用,比如不能為了得到一個全局變量而創(chuàng)建單例,單例是用于控制對象的創(chuàng)建過程的。只有真正的目的是控制對象創(chuàng)建的過程或數量時,才能考慮使用單例。在大部分情況下,單例模式是有代替方案的。比如經典的數據庫連接類被以單例實現,其實可以以對象池模式實現。

    2 使用單例模式,盡量使用饑餓模式 ,只有你能預測這個類一定會被創(chuàng)建,那么就可以使用饑餓模式。如果,一定需要推遲對象的創(chuàng)建時間。那么不要使用 Double-checked locking 之類的方法的來提高效率,這將得不償失。

    [1] DoubleCheckedLocking
    http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
    posted @ 2010-04-30 21:04 lincode 閱讀(215) | 評論 (0)編輯 收藏

    一 基本概念
    這篇文章比較清楚地講述了字符集和編碼的基本概念
    http://www.regexlab.com/zh/encoding.htm

    摘抄:

    各個國家和地區(qū)所制定的不同 ANSI 編碼標準中,都只規(guī)定了各自語言所需的“字符”。比如:漢字標準(GB2312)中沒有規(guī)定韓國語字符怎樣存儲。這些 ANSI 編碼標準所規(guī)定的內容包含兩層含義:

    1. 使用哪些字符。也就是說哪些漢字,字母和符號會被收入標準中。所包含“字符”的集合就叫做“字符集”。
    2. 規(guī)定每個“字符”分別用一個字節(jié)還是多個字節(jié)存儲,用哪些字節(jié)來存儲,這個規(guī)定就叫做“編碼”。

    各個國家和地區(qū)在制定編碼標準的時候,“字符的集合”和“編碼”一般都是同時制定的。因此,平常我們所說的“字符集”,比如:GB2312, GBK, JIS 等,除了有“字符的集合”這層含義外,同時也包含了“編碼”的含義。

    UNICODE 字符集”包含了各種語言中使用到的所有“字符”。用來給 UNICODE 字符集編碼的標準有很多種,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。


    二 eclipse 中對于編碼方式的設置

    1 源文件的編碼設置

    preference -> general -> Content Types 
    右邊選擇文件類型,右下更新 缺省編碼方式

    2 控制臺的編碼設置
    Run -> Run configuration( 或 Debug configuration)
    右邊選項卡中 common, 一般為最后一項
    在 console encoding 的 other 中選取需要的 編碼方式

    三 java 中的 編碼轉換

    byte[] bytes = oldStr.getBytes(); //默認編碼方式下的字節(jié)數組
    String newStr = new String( bytes, "UTF-8" ); //轉換成 UTF-8 編碼下的字符串


     
    posted @ 2010-04-29 23:31 lincode 閱讀(261) | 評論 (0)編輯 收藏

    Java 中函數參數傳遞和函數返回值都是以值方式傳遞的。當然,對于對象,我們也可以說是引用的方式傳遞,其實傳遞也是值,只不過是引用值。引用是一個對象的別名,對于引用的修改就是對于對象本身的修改。

    為了便于理解還是可以說成是兩種類型,原始類型以值方式傳遞,對象以引用方式傳遞。

    向函數里傳遞參數,已經有很多java教程講解了。這里主要記錄一個 函數返回值的問題。在返回一個對象時,是返回值本身的應用,還是拷貝這個值,再傳拷貝的引用呢。這是需要考慮清楚的。

    這個問題,是我在 不同手機上調試 J2ME 程序時遇到的。

    具體如下,這是一個關于時間的工具類。我發(fā)覺 Calendar 的 getTime() 在有的機器下 如 Nokia,返回的 Calendar 當前時間的一個拷貝的引用,而 SAMSUNG 則直接返回 Calendar 的當前時間的引用。這導致,我在想得到一個時間所在那一的起始時間和結束時間時,總是得到相同的值,即后一次調用的值。按照,比較正常的理解,這里應該返回拷貝的引用比較正確,就是說 SAMSUNG 的 JVM 實現有些問題。面對這種情況,我只能先用 Date 類 返回 一個 long 值,再用 long 值構造一個新日期,即日歷當前日期的拷貝,返回這個拷貝。

    修改函數中的最后一行為
    return new Date(fCalendar.getTime().getTime());

        private static Date fCalendar = Calendar.getInstance();


        
    /**
                 * Get the beginning of a day
                 * 
    @param date <description>
                 * 
    @return <description>
                 
    */
        
    public static Date getBeginOfDay( final Date pDate ) {
            
           fCalendar.setTime( pDate );
           
    try{
               fCalendar.set( Calendar.HOUR_OF_DAY, 
    0 );
               fCalendar.set( Calendar.MINUTE, 
    0 );
               fCalendar.set( Calendar.SECOND, 
    0 );
            }
    catch(ArrayIndexOutOfBoundsException ex){
                ex.printStackTrace();
            } 
            
    return fCalendar.getTime();
        }
       
        
    /**
                 * Get the end of a day
                 * 
    @param date <description>
                 * 
    @return <description>
                 
    */
        
    public static Date getEndOfDay( final Date pDate ){
            
           fCalendar.setTime( pDate );
           
    try{
               fCalendar.set( Calendar.HOUR_OF_DAY, 
    23 );
               fCalendar.set( Calendar.MINUTE, 
    59 );
               fCalendar.set( Calendar.SECOND, 
    59 );
            }
    catch(ArrayIndexOutOfBoundsException ex){
                ex.printStackTrace();
            }
            
    return fCalendar.getTime();
        }





    posted @ 2010-02-24 21:36 lincode 閱讀(2327) | 評論 (0)編輯 收藏
    主站蜘蛛池模板: 国产成人免费A在线视频| 国产亚洲午夜精品| 2022年亚洲午夜一区二区福利| 在线精品亚洲一区二区三区| 亚洲精品无码久久毛片| 亚洲一区精品伊人久久伊人| 亚洲片一区二区三区| 区久久AAA片69亚洲| 亚洲精品乱码久久久久久按摩 | 一级毛片免费观看不卡视频| 久久免费高清视频| 日韩av无码免费播放| 久9这里精品免费视频| 91免费在线播放| www.黄色免费网站| 日本免费一区尤物| 无码专区一va亚洲v专区在线| 亚洲人成色7777在线观看不卡| 曰韩亚洲av人人夜夜澡人人爽 | 国产免费资源高清小视频在线观看| 日本成人在线免费观看| 免费在线一级毛片| 亚洲午夜国产精品无码老牛影视| 亚洲第一中文字幕| 色噜噜亚洲男人的天堂| 精品久久久久久亚洲综合网| 一级中文字幕乱码免费| 国产永久免费高清在线| 18女人水真多免费高清毛片| 无码中文字幕av免费放| www国产亚洲精品久久久日本| 亚洲女同成av人片在线观看| 亚洲成AV人片久久| 久久久久久亚洲av无码蜜芽| 国产vA免费精品高清在线观看 | 爱情岛亚洲论坛在线观看| 成人精品视频99在线观看免费| 久久国产高潮流白浆免费观看| 最近中文字幕mv免费高清视频7 | 日韩精品视频免费在线观看| 国产亚洲人成A在线V网站 |