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

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          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 閱讀(733) | 評論 (0)編輯 收藏

          這個 bug 在 xcode 4.3 以下會出現(xiàn),4.3 以后已經(jīng)修正了。
          解決方法為:找到 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。

          總結(jié)如下:
          如果,第三庫中沒有 category,Other Linker Flags 無需設置
          如果,第三方庫中有 category,需要設置為 -ObjC
          如果,某些 Xcode 版本中,出現(xiàn)問題,修改設置為 -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

          這樣就能看到,地址對應的類,函數(shù),代碼行數(shù)。這個命令只能解析出客戶代碼的位置。若是錯誤堆棧中的系統(tǒng)調(diào)用,是無法翻譯出來的。
          posted @ 2012-03-18 13:56 lincode 閱讀(1001) | 評論 (0)編輯 收藏
          Apple 提供了一個地址方向解析的服務 MKReverseGeocoder,上傳一個經(jīng)緯度,返回一個詳細的地理位置信息。但這個服務在中國不太穩(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 閱讀(1368) | 評論 (0)編輯 收藏

          定義

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

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



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


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

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

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


          OAuth 2.0

          OAuth 2.0是OAuth協(xié)議的下一版本,但不向后兼容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 閱讀(324) | 評論 (0)編輯 收藏

          名稱

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

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

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

          資源(Resources)

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

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

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

          表現(xiàn)層(Representation)

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

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

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

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

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

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

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

          綜述

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

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

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

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

          誤區(qū)

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

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

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

          如果某些動作是HTTP動詞表示不了的,你就應該把動作做成一種資源。比如網(wǎng)上匯款,從賬戶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

          因為不同的版本,可以理解成同一種資源的不同表現(xiàn)形式,所以應該采用同一個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 調(diào)用手機的原生功能,例如,獲取經(jīng)緯度,讓手機振動等。
          主頁 http://www.phonegap.com/ 。
          源碼 https://github.com/phonegap/phonegap-android 。

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

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

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

          振動的實現(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 一個反饋:
          這里 PhoneGap 使用了一個在客戶端本地實現(xiàn)的 XHRServer,具體到代碼中就是一個JAVA 類 CallbackServer。

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

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

          一 序列化原因:

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

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

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


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

          2 Parcelabel 的實現(xiàn),需要在類中添加一個靜態(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 閱讀(22138) | 評論 (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時調(diào)用。設置在該方法中,還以Bundle中可以提出用于創(chuàng)建該 Activity 所需的信息。
          onStart():activity變?yōu)樵谄聊簧蠈τ脩艨梢姇r,即獲得焦點時,會調(diào)用。
          onResume():activity開始與用戶交互時調(diào)用(無論是啟動還是重新啟動一個活動,該方法總是被調(diào)用的)。
          onPause():activity被暫停或收回cpu和其他資源時調(diào)用,該方法用于保存活動狀態(tài)的。。
          onStop():activity被停止并轉(zhuǎn)為不可見階段及后續(xù)的生命周期事件時,即失去焦點時調(diào)用。
          onRestart():重新啟動activity時調(diào)用。該活動仍在棧中,而不是啟動新的活動。
          onDestroy():activity被完全從系統(tǒng)內(nèi)存中移除時調(diào)用,該方法被調(diào)用可能是因為有人直接調(diào)用 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ā)現(xiàn)不會再打印相同信息,但多打印了一行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、不設置Activity的android:configChanges時,切屏會重新調(diào)用各個生命周期,切橫屏時會執(zhí)行一次,切豎屏時會執(zhí)行兩次

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

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





          posted @ 2011-09-16 10:32 lincode 閱讀(3371) | 評論 (1)編輯 收藏
          主站蜘蛛池模板: 榆中县| 云龙县| 环江| 永嘉县| 三河市| 浙江省| 濮阳市| 汝州市| 武穴市| 通州市| 辛集市| 宾阳县| 庆元县| 陇西县| 永兴县| 金湖县| 松潘县| 上虞市| 金堂县| 同江市| 富川| 开化县| 县级市| 定襄县| 抚州市| 兴义市| 陈巴尔虎旗| 扎鲁特旗| 松溪县| 蓝田县| 临泽县| 磴口县| 涞水县| 内黄县| 日照市| 英山县| 烟台市| 广饶县| 承德市| 中江县| 孝昌县|