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

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

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

    隨筆 - 35  文章 - 21  trackbacks - 0
    <2011年9月>
    28293031123
    45678910
    11121314151617
    18192021222324
    2526272829301
    2345678

    常用鏈接

    留言簿

    隨筆分類

    隨筆檔案

    文章分類

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    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) | 評(píng)論 (0)編輯 收藏

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

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

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

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

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

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

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

    DOUHttpRequest 是對(duì) ASIHTTPRequest 的一個(gè)簡(jiǎn)單封裝。這些代碼可以 繼承自 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) | 評(píng)論 (0)編輯 收藏

    定義

    OAuth(開放授權(quán))是一個(gè)開放標(biāo)準(zhǔn),允許用戶讓第三方應(yīng)用訪問該用戶在某一網(wǎng)站上存儲(chǔ)的私密的資源(如照片,視頻,聯(lián)系人列表),而無需將用戶名和密碼提供給第三方應(yīng)用。

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



    認(rèn)證和授權(quán)過程


    在認(rèn)證和授權(quán)的過程中涉及的三方包括:
    • 服務(wù)提供方,用戶使用服務(wù)提供方來存儲(chǔ)受保護(hù)的資源,如照片,視頻,聯(lián)系人列表。
    • 用戶,存放在服務(wù)提供方的受保護(hù)的資源的擁有者。
    • 客戶端,要訪問服務(wù)提供方資源的第三方應(yīng)用,通常是網(wǎng)站,如提供照片打印服務(wù)的網(wǎng)站。在認(rèn)證過程之前,客戶端要向服務(wù)提供者申請(qǐng)客戶端標(biāo)識(shí)。

    使用OAuth進(jìn)行認(rèn)證和授權(quán)的過程如下所示:

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


    OAuth 2.0

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

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

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

    名稱

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

    如果一個(gè)架構(gòu)符合REST原則,就稱它為RESTful架構(gòu)。

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

    資源(Resources)

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

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

    所謂"上網(wǎng)",就是與互聯(lián)網(wǎng)上一系列的"資源"互動(dòng),調(diào)用它的URI。

    表現(xiàn)層(Representation)

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

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

    URI只代表資源的實(shí)體,不代表它的形式。嚴(yán)格地說,有些網(wǎng)址最后的".html"后綴名是不必要的,因?yàn)檫@個(gè)后綴名表示格式,屬于"表現(xiàn)層"范疇,而URI應(yīng)該只代表"資源"的位置。它的具體表現(xiàn)形式,應(yīng)該在HTTP請(qǐng)求的頭信息中用Accept和Content-Type字段指定,這兩個(gè)字段才是對(duì)"表現(xiàn)層"的描述。

    狀態(tài)轉(zhuǎn)化(State Transfer)

    訪問一個(gè)網(wǎng)站,就代表了客戶端和服務(wù)器的一個(gè)互動(dòng)過程。在這個(gè)過程中,勢(shì)必涉及到數(shù)據(jù)和狀態(tài)的變化。

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

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

    綜述

    綜合上面的解釋,我們總結(jié)一下什么是RESTful架構(gòu):

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

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

      (3)客戶端通過四個(gè)HTTP動(dòng)詞,對(duì)服務(wù)器端資源進(jìn)行操作,實(shí)現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。

    誤區(qū)

    RESTful架構(gòu)有一些典型的設(shè)計(jì)誤區(qū)。

    最常見的一種設(shè)計(jì)錯(cuò)誤,就是URI包含動(dòng)詞。因?yàn)?資源"表示一種實(shí)體,所以應(yīng)該是名詞,URI不應(yīng)該有動(dòng)詞,動(dòng)詞應(yīng)該放在HTTP協(xié)議中。

    舉例來說,某個(gè)URI是/posts/show/1,其中show是動(dòng)詞,這個(gè)URI就設(shè)計(jì)錯(cuò)了,正確的寫法應(yīng)該是/posts/1,然后用GET方法表示show。

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

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

    正確的寫法是把動(dòng)詞transfer改成名詞transaction,資源不能是動(dòng)詞,但是可以是一種服務(wù):

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

    另一個(gè)設(shè)計(jì)誤區(qū),就是在URI中加入版本號(hào)

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

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

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

    因?yàn)椴煌陌姹荆梢岳斫獬赏环N資源的不同表現(xiàn)形式,所以應(yīng)該采用同一個(gè)URI。版本號(hào)可以在HTTP請(qǐng)求頭信息的Accept字段中進(jìn)行區(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) | 評(píng)論 (0)編輯 收藏

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

    PhoneGap 在早期,應(yīng)該是使用 WebView 的 addJavaScriptInterface 方法,來為 JS 提供調(diào)用原生功能可能。addJavaScriptInterface ,可以將一個(gè) Java 對(duì)象綁定到一個(gè) JS 對(duì)象。是的,JS對(duì)象可以調(diào)用 Java方法。但在 PhoneGap 1.0.0 這個(gè)版本中,PhoneGap 改變了方法。

    以振動(dòng)功能為例,我們可以看一下程序調(diào)用的流程:

    1 在 JS 中,啟動(dòng)命令

    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]));

    這時(shí),WebView 就會(huì)企圖彈出一個(gè)窗口。這時(shí)使用 android 提供的 WebChromeClient 的 API 就可以截獲 WebView 的這個(gè)動(dòng)作 。

    2 JAVA 中,處理命令
    WebView 的 WebChromClient 實(shí)現(xiàn)了下面這個(gè)函數(shù):

    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 會(huì)根據(jù)收到參數(shù),將命令分發(fā)給特定的 Plugin。這個(gè)例子中,接收的 plugin 是:Notification。
    落實(shí)到 Notification 的 exec 函數(shù):會(huì)執(zhí)行這一行: this.vibrate(args.getLong(0));

    振動(dòng)的實(shí)現(xiàn)為:

     

     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 處理完后的數(shù)據(jù),需要給 JS 一個(gè)反饋:
    這里 PhoneGap 使用了一個(gè)在客戶端本地實(shí)現(xiàn)的 XHRServer,具體到代碼中就是一個(gè)JAVA 類 CallbackServer。

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

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

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

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

    pt: point(磅),是一個(gè)標(biāo)準(zhǔn)的長(zhǎng)度單位,1pt=1/72英寸,用于印刷業(yè),非常簡(jiǎn)單易用; 

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

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

    一 序列化原因:

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

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

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


    實(shí)現(xiàn):
    1 Serializable 的實(shí)現(xiàn),只需要繼承  implements Serializable 即可。這只是給對(duì)象打了一個(gè)標(biāo)記,系統(tǒng)會(huì)自動(dòng)將其序列化。

    2 Parcelabel 的實(shí)現(xiàn),需要在類中添加一個(gè)靜態(tài)成員變量 CREATOR,這個(gè)變量需要繼承 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) | 評(píng)論 (0)編輯 收藏
    生命周期
    Android 系統(tǒng)在Activity 生命周期中加入一些鉤子,我們可以在這些系統(tǒng)預(yù)留的鉤子中做一些事情。
    例舉了 7 個(gè)常用的鉤子:
    protected void onCreate(Bundle savedInstanceState)
    protected void onStart()
    protected void onResume()
    protected void onPause()
    protected void onStop()
    protected void onRestart()
    protected void onDestroy()

    簡(jiǎn)要說明:
    onCreate(Bundle savedInstanceState):創(chuàng)建activity時(shí)調(diào)用。設(shè)置在該方法中,還以Bundle中可以提出用于創(chuàng)建該 Activity 所需的信息。
    onStart():activity變?yōu)樵谄聊簧蠈?duì)用戶可見時(shí),即獲得焦點(diǎn)時(shí),會(huì)調(diào)用。
    onResume():activity開始與用戶交互時(shí)調(diào)用(無論是啟動(dòng)還是重新啟動(dòng)一個(gè)活動(dòng),該方法總是被調(diào)用的)。
    onPause():activity被暫停或收回cpu和其他資源時(shí)調(diào)用,該方法用于保存活動(dòng)狀態(tài)的。。
    onStop():activity被停止并轉(zhuǎn)為不可見階段及后續(xù)的生命周期事件時(shí),即失去焦點(diǎn)時(shí)調(diào)用。
    onRestart():重新啟動(dòng)activity時(shí)調(diào)用。該活動(dòng)仍在棧中,而不是啟動(dòng)新的活動(dòng)。
    onDestroy():activity被完全從系統(tǒng)內(nèi)存中移除時(shí)調(diào)用,該方法被調(diào)用可能是因?yàn)橛腥酥苯诱{(diào)用 finish()方法 或者系統(tǒng)決定停止該活動(dò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ā)現(xiàn)不會(huì)再打印相同信息,但多打印了一行onConfigChanged

    onSaveInstanceState
    onPause
    onStop
    onDestroy
    onCreate
    onStart
    onRestoreInstanceState
    onResume
    onConfigurationChanged

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

    onConfigurationChanged

    6 切回豎屏

    onConfigurationChanged
    onConfigurationChanged

    總結(jié):

    1、不設(shè)置Activity的android:configChanges時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次,切豎屏?xí)r會(huì)執(zhí)行兩次

    2、設(shè)置Activity的android:configChanges="orientation"時(shí),切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫、豎屏?xí)r只會(huì)執(zhí)行一次

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





    posted @ 2011-09-16 10:32 lincode 閱讀(3370) | 評(píng)論 (1)編輯 收藏
    主站蜘蛛池模板: 免费一级毛片清高播放| ww4545四虎永久免费地址| 男人扒开添女人下部免费视频| 亚洲中文字幕无码爆乳| 国产99在线|亚洲| 亚洲综合国产成人丁香五月激情| 国产亚洲中文日本不卡二区| 久久亚洲精品国产精品婷婷| 亚洲中文无码亚洲人成影院| 亚洲熟妇无码av另类vr影视| 亚洲欧美成人av在线观看| 亚洲av无码专区在线观看下载 | 免费A级毛片无码免费视| 国产一卡二卡四卡免费| 韩国免费一级成人毛片| 成年女人色毛片免费看| 青青青国产免费一夜七次郎| 国产精品色午夜视频免费看| 成人伊人亚洲人综合网站222| 伊人久久精品亚洲午夜| 亚洲AV综合色区无码一区爱AV| 亚洲老熟女@TubeumTV| 亚洲成a人片在线看| 亚洲av无一区二区三区| 亚洲免费无码在线| 久久久免费的精品| 香蕉97超级碰碰碰免费公| 国产美女被遭强高潮免费网站| 亚洲国产aⅴ综合网| 亚洲成a人片在线观看日本| 91久久亚洲国产成人精品性色| 亚洲成a人片在线看| 污视频网站免费在线观看| a级片免费观看视频| 4虎永免费最新永久免费地址| 日本免费一区二区三区最新vr| 亚洲中文字幕成人在线| 久久亚洲熟女cc98cm| 日本亚洲欧美色视频在线播放| 99久久免费国产精精品| 国产免费看JIZZ视频|