17.《APP研發(fā)錄》筆記

一、重構(gòu)咪奖,夜未眠
1.重新規(guī)劃Android項(xiàng)目結(jié)構(gòu)
第一步辅鲸,建立AndroidLib類(lèi)庫(kù),將與業(yè)務(wù)無(wú)關(guān)的邏輯轉(zhuǎn)移到AndroidLib展箱。activity(無(wú)業(yè)務(wù)無(wú)關(guān)的Activity基類(lèi))旨枯、net(網(wǎng)絡(luò)底層封裝)、cache(緩存數(shù)據(jù)和圖片的相關(guān)處理)析藕、ui(自定義控件)召廷、utils(與業(yè)務(wù)無(wú)關(guān)的公用方法,比如對(duì)SharedPreferences的封裝)
第二步账胧,將主項(xiàng)目中的類(lèi)分門(mén)別類(lèi)地進(jìn)行劃分竞慢,放置在各種包中。activity(將不同模塊的Activity劃分到不同的包下)治泥、adapter(所有適配器放在一起)筹煮、entity(所有的實(shí)體都放在一起)、db(SQLite相關(guān)邏輯的封裝)居夹、engine(業(yè)務(wù)相關(guān)的類(lèi))败潦、ui(自定義控件)本冲、utils(公用方法)、interfaces(真正意義上的接口劫扒,命名以I作為開(kāi)頭)檬洞、listener(基于Listener的接口,命名以O(shè)n作為開(kāi)頭)
2.為Activity定義新的生命周期
拆分成子方法
3.統(tǒng)一事件編程模型
點(diǎn)擊方法用匿名內(nèi)部類(lèi)實(shí)現(xiàn)
4.實(shí)體化編程
JSON用GSON等第三方類(lèi)解析沟饥,使用fastJSON時(shí)混淆文件要添加:--keepattributes Signature,--keepattributes Annotation
實(shí)體生成器:EntityGenerater
頁(yè)面跳轉(zhuǎn)中使用實(shí)體時(shí)不建議使用全局變量添怔,可能被回收然后App崩潰∠涂酰可把實(shí)體實(shí)現(xiàn)Serializable然后傳送广料。
5.Adapter模板
所有Adapter都繼承自BaseAdapter,從構(gòu)造函數(shù)注入List<>這樣的數(shù)據(jù)集合幼驶。
6.類(lèi)型安全轉(zhuǎn)換函數(shù)
對(duì)于一個(gè)Object類(lèi)型的對(duì)象艾杏,我們對(duì)其直接使用字符串操作函數(shù)toString,當(dāng)其為null時(shí)就會(huì)崩潰盅藻,所以實(shí)現(xiàn)一個(gè)判斷是否為空的轉(zhuǎn)換函數(shù)购桑。
如果長(zhǎng)度不夠,那么招行substring函數(shù)時(shí)萧求,就會(huì)崩潰其兴。所以在使用時(shí)要判斷start和end兩個(gè)參數(shù)是否越界了。

二夸政、Android網(wǎng)絡(luò)底層框架設(shè)計(jì)
1.網(wǎng)絡(luò)低層封裝
不推薦使用AsyncTask來(lái)封裝網(wǎng)絡(luò)底層元旬,因?yàn)榭蓴U(kuò)展性不高。
現(xiàn)在一般使用RxJava+Retrofit
實(shí)例:使用原生的ThreadPoolExecutor+Runnable+Handler
2.App數(shù)據(jù)緩存設(shè)計(jì)
減少調(diào)用次數(shù)守问,然后把獲取的數(shù)據(jù)保存在A(yíng)pp上匀归。
3.MockService
當(dāng)API沒(méi)做好時(shí),自己模擬相關(guān)的的接口實(shí)現(xiàn)
4.用戶(hù)登錄
登錄成功后場(chǎng)景:點(diǎn)擊登錄按鈕耗帕,進(jìn)入登錄頁(yè)面LoginActivity穆端,登錄成功后,直接進(jìn)入個(gè)人中心仿便,這種情況一路執(zhí)行startActivity()就能達(dá)到目的体啰;在頁(yè)面A,想跳轉(zhuǎn)到頁(yè)面B嗽仪,并攜帶一些參數(shù)荒勇,卻發(fā)現(xiàn)沒(méi)有登錄,于是先跳轉(zhuǎn)到登錄頁(yè)闻坚,登錄成功后沽翔,再跳轉(zhuǎn)到B頁(yè)面,同時(shí)仍然帶著那些參數(shù),用setResult實(shí)現(xiàn)仅偎;在頁(yè)面A跨蟹,執(zhí)行某個(gè)操作,卻發(fā)現(xiàn)沒(méi)有登錄橘沥,于是跳轉(zhuǎn)到登錄面窗轩,登錄成功后再回到頁(yè)面A,繼續(xù)執(zhí)行該操作威恼,也是用setResult來(lái)完成回調(diào)品姓。
自動(dòng)登錄,不推薦本地保存用戶(hù)名和密碼箫措,使用Cookie機(jī)制,也叫Token衬潦。登錄成功后斤蔓,會(huì)從服務(wù)器獲取到一個(gè)Cookie,取出來(lái)放在本地文件中即可镀岛。當(dāng)用戶(hù)注銷(xiāo)時(shí)弦牡,要清空本地的Cookie。
Cookie過(guò)期統(tǒng)一處理:加一個(gè)onCookieExpired回調(diào)方法漂羊。
防止黑客刷庫(kù):登錄接口增加第三個(gè)參數(shù)驾锰,比如驗(yàn)證碼;同一IP短時(shí)間內(nèi)頻繁訪(fǎng)問(wèn)時(shí)要求輸入驗(yàn)證碼走越,用WebView實(shí)現(xiàn)椭豫。
5.HTTP頭中的奧妙
請(qǐng)求、時(shí)間校準(zhǔn)旨指、開(kāi)啟gzip壓縮

三赏酥、Android經(jīng)典場(chǎng)景設(shè)計(jì)
1.App圖片緩存設(shè)計(jì)
ImageLoader設(shè)計(jì)原理:在顯示圖片時(shí),先在內(nèi)存中查找谆构;如果沒(méi)有裸扶,就去本地查找;如果還沒(méi)有搬素,就開(kāi)一個(gè)新線(xiàn)程去下載這張圖片呵晨,下載成功會(huì)把圖片同時(shí)緩存到內(nèi)存和本地。對(duì)圖片是軟引用形式熬尺,所有內(nèi)存中圖片會(huì)在內(nèi)存不足的時(shí)候被系統(tǒng)回收摸屠。
Freso原理:設(shè)計(jì)了一個(gè)Image Pipeline的要信,它負(fù)責(zé)先后檢查內(nèi)存猪杭、磁盤(pán)文件餐塘,如果都沒(méi)有就去從網(wǎng)絡(luò)下載圖片。三層緩存:Bitmap緩存皂吮、內(nèi)存緩存戒傻、磁盤(pán)緩存税手。
2.對(duì)網(wǎng)絡(luò)流量進(jìn)行優(yōu)化
通信層面的優(yōu)化:返回的數(shù)據(jù)存在于1KB時(shí)用gzip壓縮;數(shù)據(jù)傳遞遵守JSON協(xié)議需纳,推薦ProtoBuffer協(xié)議芦倒;減少網(wǎng)絡(luò)訪(fǎng)問(wèn)次數(shù);使用TCP長(zhǎng)連接不翩;建立取消網(wǎng)絡(luò)請(qǐng)求機(jī)制兵扬,當(dāng)一個(gè)頁(yè)面沒(méi)有請(qǐng)求完數(shù)據(jù),跳轉(zhuǎn)到另一個(gè)頁(yè)面之前口蝠,把之前的網(wǎng)絡(luò)請(qǐng)求都取消器钟;增加重試機(jī)制。
圖片策略?xún)?yōu)化:確保下載的每張圖妙蔗,都符合ImageView控件的大邪涟浴;低流量模式眉反,降低圖片質(zhì)量昙啄;極速模式,沒(méi)有圖片寸五,只有文字梳凛。
3.城市列表的設(shè)計(jì)
4.App與HTML5的交互
用PhoneGap太重,把交互操作在底層封裝梳杏,然后給開(kāi)發(fā)人員使用韧拒。
對(duì)于經(jīng)常需要改動(dòng)的頁(yè)面,做成H5頁(yè)面秘狞,在A(yíng)pp中以WebView的形式加載叭莫。H5開(kāi)發(fā)周期短,但慢烁试」统酰可以做兩套頁(yè)面,Native一套减响,H5一套靖诗,在A(yíng)pp中設(shè)置一個(gè)變量,判斷該頁(yè)面用哪個(gè)支示。變量從后臺(tái)中獲取刊橘。
5.消滅全局變量
在內(nèi)存不足時(shí),系統(tǒng)會(huì)回收全局變量颂鸿,會(huì)導(dǎo)致APP崩潰促绵。解決這個(gè)問(wèn)題,使用序列化技術(shù)。
對(duì)社交和電商類(lèi)App而言败晴,頁(yè)面繁多浓冒,沒(méi)必要保存頁(yè)面狀態(tài),直接讓頁(yè)面重新執(zhí)行一遍onCreate方法尖坤,丟失的數(shù)據(jù)讓用戶(hù)重新操作稳懒。使用MVVM設(shè)計(jì)模式,可以把ViewModel序列化到本地慢味,用以保存頁(yè)面场梆。
SharedPreferences中存放的變量數(shù)量應(yīng)嚴(yán)格控制。
User是唯一例外的全局變量:序列化到本地纯路,避免崩潰

四或油、Android命名規(guī)劃和編碼規(guī)范
1.Android命名規(guī)范
Activity、Adapter感昼、Entity都為結(jié)尾装哆,控件縮寫(xiě),常量命名等

2.Android編碼規(guī)范
分門(mén)另類(lèi)存放各種類(lèi)定嗓,Layout中使用的常量定義在Strings.xml中,Layout控件字體大小萍桌,定義在dimens.xml中宵溅,拆分onCreate,JSON解析用第三方庫(kù)上炎,頁(yè)面?zhèn)髦涤肐ntent恃逻,控件事件用匿名內(nèi)部類(lèi),Activity中不要嵌套內(nèi)部類(lèi)藕施,實(shí)體不要在不同模塊間共享寇损,節(jié)省內(nèi)存,使用ArrayList而不是HashMap裳食,圖片處理用第三方矛市,盡量使用ApplicationContext代替Context,數(shù)據(jù)類(lèi)型轉(zhuǎn)換一定要校驗(yàn)诲祸,使用常量代替枚舉浊吏。

3.統(tǒng)一代碼格式
團(tuán)隊(duì)中所有人使用同一種代碼格式

五、Crash異常收集與統(tǒng)計(jì)
1.異常收集
設(shè)計(jì)一個(gè)CrashHandler類(lèi)救氯,繼承自UncaughtExceptionHandler找田,處理未捕獲的異常∽藕基本關(guān)鍵方法就handleException墩衙,做三件事:發(fā)錯(cuò)誤日志到服務(wù)器,給用戶(hù)崩潰前的友好提示,把錯(cuò)誤日志記錄到SD卡漆改。

2.異常收集與統(tǒng)計(jì)
要么記錄到第三方平臺(tái)心铃,要么記錄到自己的數(shù)據(jù)庫(kù)中然后處理

六、Crash異常分析
1.Java語(yǔ)法相關(guān)的異常
空指針NullPointException籽懦、角標(biāo)越界IndexOutOfBoundsException/StringIndexOutOfBoundsException/ArrayIndexOutOfBoundsException于个、試圖調(diào)用一個(gè)空對(duì)象的方法、類(lèi)型轉(zhuǎn)換異常暮顺、數(shù)字轉(zhuǎn)換錯(cuò)誤厅篓,聲明數(shù)組長(zhǎng)度為-1、遍歷集合同時(shí)刪除其中元素捶码、比較器使用不當(dāng)羽氮、當(dāng)除數(shù)為0、不能隨便使用的asList惫恼、又有類(lèi)找不到了(一):ClassNotFoundException档押、又有類(lèi)找不到了(二):NoClassDefFoundError

2.Activity相關(guān)的異常
找不到Activity、不能實(shí)例化Activity祈纯、找不到Service令宿、不能啟動(dòng)BroadcastReceiver、startActivityForResult不能回傳腕窥、猴急的Fragment

3.序列化相關(guān)的異常
實(shí)體對(duì)象不支持序列化粒没、序列化時(shí)未指定ClassLoader、反序列化時(shí)發(fā)現(xiàn)類(lèi)找不到:被ProGuard混淆導(dǎo)致的崩潰簇爆、反序列化時(shí)發(fā)現(xiàn)類(lèi)找不到:傳入畸形數(shù)據(jù)癞松、反序列化時(shí)出錯(cuò)

4.列表相關(guān)的異常
Adapter數(shù)據(jù)源變化但是沒(méi)通知ListView、ListView滾動(dòng)時(shí)點(diǎn)擊刷新按鈕后崩潰入蛆、AbsListView的obtainView返回空指針响蓉、Adapter數(shù)據(jù)源變化但是沒(méi)調(diào)用notifyDataSetChanged

5.窗體相關(guān)的異常
窗口句柄泄露、View not attached to window manager哨毁、窗體在不恰當(dāng) 的時(shí)候獲取了焦點(diǎn)枫甲、token null is not for an application、permission denied for this window type挑庶、is your activity running言秸、添加窗體失敗、AlertDialog.resolveDialogTheme迎捺、The specified child already has a parent举畸、子線(xiàn)程不能修改UI、不能在子線(xiàn)程操作AlertDialog和Toast

6.資源相關(guān)的異常
Resources$NotFoundException凳枝、StackOverFlowError抄沮、UnsatisfiedLinkError跋核、InfiateException之FileNotFoundException、InfiateException之缺少構(gòu)造器叛买、InfiateException之style與android:textStyle的區(qū)別砂代、TransactionTooLargeException

7.系統(tǒng)碎片化相關(guān)的異常
NoSuchMethodError、RemoteViews率挣、pointerIndex out of range刻伊、SecurityException之一:Intent中圖片太大、SecurityException之二:動(dòng)態(tài)加載其他apk的activity椒功、之三:No permission to modify thread捶箱、view的getDrawingCache()返回null、DeadObjectException动漾、Android 2.1 不支持SSL丁屎、ViewFlipper引發(fā)的血案、ActivityNotFundException旱眯、Android 2.2 不支持xlargeScreens晨川、Package manager has died、SpannableString與富文本字符串删豺、Can not perform this action agter onSaveInstanceState共虑、Service Intent must be explicit

8.SQLite相關(guān)的異常
No transaction is active、忘記關(guān)閉Cursor呀页、數(shù)據(jù)庫(kù)被鎖定看蚜、試圖再打開(kāi)已經(jīng)關(guān)閉的對(duì)象、文件加密了或無(wú)數(shù)據(jù)庫(kù)赔桌、WebView中SQLLite緩存導(dǎo)致的崩潰、磁盤(pán)讀寫(xiě)錯(cuò)誤渴逻、android_metadate表不存在疾党、android_metadata表中l(wèi)ocale字段、數(shù)據(jù)庫(kù)或磁盤(pán)滿(mǎn)了

9.不明覺(jué)厲的異常
內(nèi)存溢出惨奕、Verify Failed

10.其他情況的異常
TimeoutException雪位、JSON解析異常、JSONArray在初始化時(shí)為空梨撞、第三方SDK拋出的Crash雹洗、兩個(gè)不同類(lèi)型的View有相同的id、LayoutInflater.from().inflate()使用不當(dāng)導(dǎo)致的崩潰卧波、ViewGroup中的玄機(jī)时肿、Monkey點(diǎn)擊過(guò)快導(dǎo)致的崩潰、圖片寬高為0港粱、不能重復(fù)添加組件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末螃成,一起剝皮案震驚了整個(gè)濱河市旦签,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌寸宏,老刑警劉巖宁炫,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異氮凝,居然都是意外死亡羔巢,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)罩阵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)竿秆,“玉大人,你說(shuō)我怎么就攤上這事永脓∨鄞牵” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵常摧,是天一觀(guān)的道長(zhǎng)搅吁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)落午,這世上最難降的妖魔是什么谎懦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮溃斋,結(jié)果婚禮上界拦,老公的妹妹穿的比我還像新娘。我一直安慰自己梗劫,他們只是感情好享甸,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著梳侨,像睡著了一般蛉威。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上走哺,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天蚯嫌,我揣著相機(jī)與錄音,去河邊找鬼丙躏。 笑死择示,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晒旅。 我是一名探鬼主播栅盲,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼敢朱!你這毒婦竟也來(lái)了剪菱?” 一聲冷哼從身側(cè)響起摩瞎,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎孝常,沒(méi)想到半個(gè)月后旗们,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡构灸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年上渴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喜颁。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡稠氮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出半开,到底是詐尸還是另有隱情隔披,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布寂拆,位于F島的核電站奢米,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纠永。R本人自食惡果不足惜鬓长,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尝江。 院中可真熱鬧涉波,春花似錦、人聲如沸炭序。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惭聂。三九已至城侧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彼妻,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工豆茫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侨歉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓揩魂,卻偏偏與公主長(zhǎng)得像幽邓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子火脉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,325評(píng)論 25 707
  • 整個(gè)高中似乎都是吊兒郎當(dāng)?shù)倪^(guò)來(lái)的担巩,所以高考的成績(jī)可想而知。高考考下來(lái)没炒,分不夠上二本涛癌,讀了個(gè)預(yù)科。 到了大學(xué)才知道送火,...
    023木木木閱讀 480評(píng)論 0 0
  • 水晶的燈光 美麗的華裳 你一個(gè)人孤獨(dú)的等著散場(chǎng) 風(fēng)里聽(tīng)見(jiàn)了誰(shuí)的歌唱 ……
    南國(guó)雪閱讀 344評(píng)論 3 0