Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android產品研發(十)--)不使用靜態變量保存數據

android產品研發(十)--)不使用靜態變量保存數據

編輯:關於Android編程

上一篇文章中我們講解了Android中的幾種常見網絡協議:xml,json,protobuf等,以及各自的優缺點,一般而言主要我們的App涉及到了網絡傳輸都會有這方面的內容,具體可根據項目的需求確定各自的網絡傳輸協議。這裡可參考 android產品研發(九)–>App網絡傳輸協議

而本文講解的其實並不是一個技術方面,而是一個android產品研發過程中的技巧:盡量不使用靜態變量保存核心數據。這是為什麼呢?這是因為android的進程並不是安全的,包括application對象以及靜態變量在內的進程級別變量並不會一直呆著內存裡面,它會被kill掉,它真的有可能會被kill掉,真的真的,重要的事情說三遍。與大家普遍的看法不同之處在於,實際上app不會重新開始啟動。Android系統會創建一個新的Application 對象,然後啟動上次用戶離開時的activity以造成這個app從來沒有被kill掉得假象。而這時候靜態變量等數據由於進程已經被殺死而被初始化,所以就有了我們的不推薦在靜態變量(包括Application中保存全局數據靜態數據)的觀點。

最近我們的產品友友用車就遇到了這樣的問題,下面我們詳細的說明一下這個問題以及解決方案。在友友用車下單的過程中有一個當前行程的頁面,該頁面就是用戶開車過程中需要展示的頁面,主要用於展示當前用戶的用車費用,行駛裡程,用車時長,還車網點等信息。具體如下圖:
這裡寫圖片描述

而在當前行程頁面中App端有一個輪訓請求,大概每隔一分鐘會請求一次服務器,用於更新用戶的用車費用,行駛裡程,用車時長還車網點等信息。用戶可以在當前行程頁面停留很長的時間。需要注意的是這裡還有一個更換還車網點的按鈕,點擊這個按鈕會跳轉到更換還車網點的頁面,從中會選擇用戶的常用網點,而這時候需要傳遞一個參數:用戶的訂單ID,此時用戶的訂單ID保存在了系統的靜態變量中。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPtTax7C8uMzst/7O8cb3tsuxqMHL0ru49mJ1Z6Osy7W1xMrH1Nq1scew0NCzzNKzw+a147v3uPy4xLu7s7XN+LXjx+vH87Oj08PN+LXjyrHDu9PQyc+0q7aptaVJRKOstvhBcHC2y7XEtPrC68rHxdC2z7TLyrG1xLaptaVJRMrHt/HOqr/Vo6zI9LK7zqq/1bXEu7DU8snPtKsuPC9wPg0KPHByZSBjbGFzcz0="brush:java;"> if (!TextUtils.isEmpty(orderId)) { builder.setOrderId(orderId); }

可以看到,如果這時候我們的orderId為空,那麼我們就不會上傳orderId,而服務器端說我們沒有上傳orderId,可能的原因就是我們的orderId這時候為空了,那麼這裡的orderId是一個靜態變量,而且我們沒有手動的置空,為什麼orderId會變為空了呢?好吧,看一下服務器端的用戶請求日志。

下面的這一段日志是用戶這段時間所有的網絡請求日志,當然也包括更改還車地點的請求服務器的日志:

[log@iZ28tw9apzsZ UUAccess-App]$ cat CmdAccess4Stat.log.2016-06-08 | grep '2119489256'
2016-06-08 11:22:52,778 1100004 229BAEC4B95E4C6ABB83F26FB7A48C88        2119489256      117.136.0.134   1465356172778   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:22:58,409 1070002 BABEDA5E46494FB4B00A2E50FD2F8F4D        2119489256      117.136.0.134   1465356178409   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:22:58,409 1130001 5F9D626DB30D442880A67D1C3A2A1C67        2119489256      117.136.0.134   1465356178409   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:22:58,862 1070002 68767819033342E5A31D03956C3FA84C        2119489256      117.136.0.134   1465356178862   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:22:58,862 1110001 6EB7CFC572E7404782512BAA26FE9D10        2119489256      117.136.0.134   1465356178862   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:22:59,029 1110002 C1039D50827D40098E3654FAD1260404        2119489256      117.136.0.134   1465356179029   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:22:59,498 1050007 DD0198099023454C889522A148F82955        2119489256      117.136.0.134   1465356179498   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:23:00,168 1130002 5E2A776EBF8743869202FB86A419580A        2119489256      117.136.0.134   1465356180168   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:23:10,038 1010003 0311997A14544D85BAA0F942650EFA84        2119489256      117.136.0.134   1465356190038   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 11:23:39,098 1070002 4B495330AC804EC3932BEBB6B6586595        2119489256      117.136.0.134   1465356219098   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:32,322 1070003 5F3F2146CDF54662A4CD5E4849D07422        2119489256      123.118.169.6   1465365692322   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:32,953 1050007 29A5FF713B11481CAABBD9084145AAA1        2119489256      123.118.169.6   1465365692953   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:33,177 1070002 AFB545D58AF648B69328D1417E73DAE6        2119489256      123.118.169.6   1465365693177   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:37,157 1110001 5CD82483782E4AF98A5FD34F2C8FB96A        2119489256      123.118.169.6   1465365697157   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:02:52,246 1050007 AF177A8CDCEC4B97B7C0EAA92B0DD7F5        2119489256      123.118.169.6   1465365772246   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:03:52,277 1050007 778CA2EC92094513A16E6EDCBB0664F0        2119489256      123.118.169.6   1465365832277   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:13,395 1010003 2DFA5673D9104412B6C5621B9E9FE19A        2119489256      123.118.169.6   1465372093395   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:15,019 1010003 D95851D7A08F4227A91A445E12105FEE        2119489256      123.118.169.6   1465372095019   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:16,984 1100004 CB208E17087C422DB56DB681E774B7C9        2119489256      123.118.169.6   1465372096984   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:17,382 1110001 CBABF14385374911BDCAEA427C1C0780        2119489256      123.118.169.6   1465372097382   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:18,011 1110002 F1D79FF8481D43F0B8861B986B458EFD        2119489256      123.118.169.6   1465372098011   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:18,716 1050007 58BDBF796411497CBD1A7CCD2F3E21AA        2119489256      123.118.169.6   1465372098716   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:18,716 1110002 8CF8D68D0A4A420C8D83A78818DBD4B7        2119489256      123.118.169.6   1465372098716   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:51:01,855 1050007 284E391D94EA48C6877F81B94E8E51DD        2119489256      123.118.169.6   1465372261855   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:51:04,784 1010002 6085D946E4AA46C884E775DE9B40987E        2119489256      123.118.169.6   1465372264784   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:51:09,249 1050007 4147044DC8014FC4B64488FFC1A0D83C        2119489256      123.118.169.6   1465372269249   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
[log@iZ28foila6mZ UUAccess-App]$  cat CmdAccess4Stat.log.2016-06-08 | grep '2119489256'
2016-06-08 14:01:32,273 1100004 C6CC832BE038415CB6590D9174025FE9        2119489256      123.118.169.6   1465365692273   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:32,577 1070002 A23766F7F63C405080C3E7FEA4C6D1E1        2119489256      123.118.169.6   1465365692577   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:37,248 1110002 4C9A9F7521954E439C25B41CB4EB1E1A        2119489256      123.118.169.6   1465365697248   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:51,142 1010003 8EBB280697D349669A9C01925D2965E8        2119489256      123.118.169.6   1465365711142   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:01:51,955 1010002 0F35494F31ED475D93AC79F08D50CAF5        2119489256      123.118.169.6   1465365711955   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:06:44,272 1110001 2AF0F04090714B6FAAC15AD4E5F7924A        2119489256      123.118.169.6   1465366004272   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 14:06:44,365 1110002 728B5A82C759443A9DBBC91D3812C14F        2119489256      123.118.169.6   1465366004365   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:13,447 1100004 40AC6AFA4A5D4E75867A6459CAFA50AD        2119489256      123.118.169.6   1465372093447   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:17,025 1070003 3A2DAC87041E4B4BAD4A73596D5A1785        2119489256      123.118.169.6   1465372097025   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:17,758 1070002 BA4F5C07FB504882826DB2B99FA8CB5D        2119489256      123.118.169.6   1465372097758   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:48:18,015 1110001 CC2F250F823044298B85C23344D36B2A        2119489256      123.118.169.6   1465372098015   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:51:02,089 1070002 BF580DD1CA2F4F29800EE631C7940747        2119489256      123.118.169.6   1465372262089   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:51:03,518 1010003 9047E26C47C94F4C90A4FA9D460C2F54        2119489256      123.118.169.6   1465372263518   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:57:26,699 1050007 A283E7F6F70E4902946716474231F01A        2119489256      123.118.169.6   1465372646699   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 15:59:04,659 1050007 D6AF179627014BBF885C41292B59F26E        2119489256      123.118.169.6   1465372744659   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:00:45,601 1050007 D8029E9094B44737ADB47C94803D2753        2119489256      123.118.169.6   1465372845601   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:00:45,890 1070002 0475136678324CAABD0D18637ED97D3C        2119489256      123.118.169.6   1465372845890   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:01:12,120 1110001 6E784DF19F3C479183A8D06FD84DBF1B        2119489256      123.118.169.6   1465372872120   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:01:48,705 1050007 AA87FE1B960B40889A9F0511187D2F3D        2119489256      123.118.169.6   1465372908705   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:02:03,148 1010003 6801B16D60364BC8826C7AB9E7D29051        2119489256      123.118.169.6   1465372923148   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:02:03,501 1010002 CCA10A3EE4D9415384A761E623FE9959        2119489256      123.118.169.6   1465372923501   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:02:05,096 1050007 837721D2E671453888E170C95849E926        2119489256      123.118.169.6   1465372925096   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:02:09,446 1070002 D161AA4123354BA4A653582B65C8077E        2119489256      123.118.169.6   1465372929446   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:04:04,784 1050007 3B8B45A4066747AD8E43DD197B47C223        2119489256      123.118.169.6   1465373044784   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:05:04,778 1050007 18AA8CE0E8C446928B230D54F068D2E6        2119489256      123.118.169.6   1465373104778   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:20,860 1070003 BC4E84F58F654CB49FD76D8BA4854D85        2119489256      117.136.0.154   1465376180860   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:20,883 1100004 184A5E0784F94A64AE5D5D7DD6E6FB86        2119489256      117.136.0.154   1465376180883   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:21,291 1070002 25738C17D2314B4382089F600EF3BEB9        2119489256      117.136.0.154   1465376181291   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:22,233 1070002 FDACF66E84DC4FF696E2FC61C368DAB0        2119489256      117.136.0.154   1465376182233   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:25,967 1110002 B5B3CC24758B4AF7AB6F3FD6185D6213        2119489256      117.136.0.154   1465376185967   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:29,674 1050003 3EB8C2993802494998603A6FBCC4243A        2119489256      117.136.0.154   1465376189674   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:35,833 1070002 655CDEEDF98E4718A17431AB9B90060C        2119489256      117.136.0.154   1465376195833   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:57,419 1050004 FD6EEDA543744A3998FB7B1E4CCFABD2        2119489256      117.136.0.154   1465376217419   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509
2016-06-08 16:56:57,837 1070002 A4BE993338094CFDBB28C1C7C72BF0C6        2119489256      117.136.0.154   1465376217837   MI 4LTE ANDROID xiaomi  2.2.0   c671b0b2b6de7aacdc2eabfa93ed4601        865372024757509

這就是出現問題的用戶的網絡請求日志,需要說明的是後台的日志分為兩個節點,所以用戶的請求日志信息被隨機的分到了兩個節點中,可以按照時間將這兩段日志信息看成是一段日志信息。

可以發現在2016-06-08 14:00:00的時候用戶每個一分鐘執行一次請求1050007請求,而這裡的1050007就是當前行程頁面的輪訓請求,大概每隔一分鐘執行一次,然後在2016-06-08 14:03的的時候就不開始執行了,這應該是用戶鎖屏之後小米手機限制後台的網絡請求,而這時候直接到了15:48分鐘,這時候用戶開始請求1010003接口,該接口就是用戶請求更換網點時請求的接口,但是這時候我們發現用戶同時調用了:1100004接口,而這個接口只有在Application的onCreate方法中調用了,所以這說明這時候應用進程已經重新啟動了,但是這時候用戶還是在當前行程頁面,並且用戶點擊了更換還車網點按鈕,而這時候由於點擊更換還車網點需要靜態變量orderId,而這時候上傳的orderId為空,所以這時候的進程靜態變量已經被初始化了。

所以綜上可以還原一下bug的出現流程:

用戶在14:00的時候停留在當前形成頁面;

用戶鎖屏,系統限制後台網絡請求,輪訓操作被限制;

系統內存吃緊,用戶應用進程被殺死,進程的靜態變量被初始化,activity界面被保留;

用戶打開屏幕,點擊更換還車網點,這時候由於進程已經被殺死,靜態變量被初始化,所以上報給服務器的orderId為空

在用戶打開屏幕的同時,系統重啟應用進程,造成應用進程沒有被殺死的假象;

好吧,既然已經知道了bug出現的原因,那麼就好解決了,既然在內存中保存數據可能被系統殺死,那麼我們可以有針對性的:

直接將數據通過intent傳遞給 Activity 。

使用官方推薦的幾種方式將數據持久化到磁盤上。

在使用數據的時候總是要對變量的值進行非空檢查。

最後我們決定將數據持久化,具體而言使用SharedPreferences來保存數據,相對來說這種方式比較簡單。下面是使用sharedpreferences保存數據的靜態工具方法:

/**
     * 獲取SP中保存的訂單ID
     *
     * @param context
     * @return
     */
    public static String getOrderId(Context context) {
        if (context == null) {
            L.i("從sp中獲取orderId失敗,context對象為空...");
            return "";
        }
        SharedPreferences sp = context.getSharedPreferences("morder", Context.MODE_PRIVATE);
        return sp.getString("morderid", "");
    }

    /**
     * 向Sp中保存orderId信息
     * @param context
     * @param orderId
     */
    public static void setOrderId(Context context, String orderId) {
        if (context == null) {
            L.i("向sp中設置orderId失敗,context對象為空...");
            return;
        }
        // 若當前orderId為null,則設置orderId為""
        if (orderId == null) {
            orderId = "";
        }

        SharedPreferences sp = context.getSharedPreferences("morder", Context.MODE_PRIVATE);
        boolean isCommitSuccess = sp.edit().putString("morderid", orderId).commit();
        if (!isCommitSuccess) {
            sp.edit().putString("morderid", orderId).commit();
        }
    }

    /**
     * 清空sp中的orderId
     * @param context
     */
    public static void clearOrderId(Context context) {
        if (context == null) {
            L.i("向sp中設置orderId失敗,context對象為空...");
            return;
        }

        SharedPreferences sp = context.getSharedPreferences("morder", Context.MODE_PRIVATE);
        sp.edit().putString("morderid", "").commit();
    }

這樣我們在使用order數據的時候可以通過sharedpreferences方法來獲取。這樣靜態變量數據被銷毀的情況就不會出現了,但是需要注意的是,當數據持久化的時候一定要在app啟動的時候清空。

總結:
在實際的android開發過程中我們不建議使用靜態變量傳遞數據,這樣會因為進程被殺死而使靜態變量初始化,我們可以使用其他數據傳輸方式:

直接將數據通過intent傳遞給 Activity 。

使用官方推薦的幾種方式將數據持久化到磁盤上。

在使用數據的時候總是要對變量的值進行非空檢查。


本文以同步至github中:https://github.com/yipianfengye/androidProject,歡迎star和follow


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved