Android開發(fā)最佳實(shí)踐


前段時(shí)間雷滋,Google公布了Android開發(fā)最佳實(shí)踐的一系列課程咖耘,涉及到一些平時(shí)開發(fā)過程中應(yīng)該保持的良好習(xí)慣以及如何使用最新的Android Design Support Library來快速實(shí)現(xiàn)官方推薦的Material Design樣式的應(yīng)用。下面是個(gè)人的學(xué)習(xí)摘要總結(jié)诱告,不對(duì)的地方請(qǐng)多多交流指點(diǎn),謝謝筑累!
1)注意對(duì)隱式Intent的運(yùn)行時(shí)檢查保護(hù)
類似打開相機(jī)崇决,發(fā)送圖片等隱式Intent,是并不一定能夠在所有的Android設(shè)備上都正常運(yùn)行键闺。例如打開相機(jī)的隱式Intent,如果系統(tǒng)相機(jī)應(yīng)用被關(guān)閉或者不存在相機(jī)應(yīng)用澈驼,又或者是相機(jī)應(yīng)用的某些權(quán)限被關(guān)閉等等情況都可能導(dǎo)致這個(gè)隱式的Intent無法正常工作辛燥。一旦發(fā)生隱式Intent找不到合適的調(diào)用組件的情況,系統(tǒng)就會(huì)拋出ActivityNotFoundException
的異常,如果我們的應(yīng)用沒有對(duì)這個(gè)異常做任何處理挎塌,那應(yīng)用就會(huì)發(fā)生Crash徘六。
預(yù)防這個(gè)問題的最佳解決方案是在發(fā)出這個(gè)隱式Intent之前調(diào)用resolveActivity
做檢查,關(guān)于這個(gè)API的解釋以及用法如下:
android_dev_patterns_implicit_intent

然后這個(gè)API的使用范例如下:

Intent intent = new Intent(Intent.ACTION_XXX);
ComponentName componentName = intent.resolveActivity(getPackageManager());
if(componentName != null) { String className = componentName.getClassName();}```

2)使用NotificationCompat兼容包來處理消息通知
為了解決Android系統(tǒng)版本差異導(dǎo)致的Notification兼容性問題榴都,Android官方提供了NotificationCompat
兼容類來幫助開發(fā)實(shí)現(xiàn)體驗(yàn)統(tǒng)一的Notification待锈。通常來說,建立一個(gè)Notification至少會(huì)有三種元素:圖標(biāo)缭贡,標(biāo)題炉擅,文本。我們通常會(huì)使用如下的代碼來實(shí)現(xiàn)一個(gè)基礎(chǔ)的Notification功能:
![](http://upload-images.jianshu.io/upload_images/1228374-bab23a2e331e5bba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
上面那段代碼阳惹,運(yùn)行時(shí)候的效果應(yīng)該如下所示:
![](http://upload-images.jianshu.io/upload_images/1228374-f07abf60d2525fc3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
為了給上面的Notification添加點(diǎn)擊之后的響應(yīng)效果谍失,我們還需要構(gòu)造一個(gè)PendingIntent
作為contentIntent,例如:

PendingIntent intent = xxx;builder.setContentIntent(intent);```

為了使得Notification更加的具有辨識(shí)度莹汤,我們還有可能做如下的設(shè)置:

android_dev_patterns_notification_set_large

從Android 4.1開始快鱼,Notification可以支持展開顯示的模式,這樣一來纲岭,Notification就演變出了下面4種不同的風(fēng)格樣式:

Notification還提供了快捷操作的功能抹竹,如下圖所示:

除了顯示在手機(jī)上的Notification,我們還可以給Notification分別設(shè)置在Wearable止潮,Auto上的不同表現(xiàn)行為窃判,例如針對(duì)可穿戴設(shè)備上顯示Notification,我們可以如下的設(shè)置:

關(guān)于更多的Wearable上的Notification相關(guān)的知識(shí)喇闸,還可以參考Pages of ContentStackable Notifications
3)Android 6.0 Marshmallow的運(yùn)行時(shí)權(quán)限
Android 6.0開始引入了新的運(yùn)行時(shí)權(quán)限檢查授權(quán)機(jī)制袄琳,替代了之前安裝應(yīng)用的時(shí)候?qū)?quán)限進(jìn)行授權(quán)的方案。為了避免6.0及以上的機(jī)器運(yùn)行發(fā)生運(yùn)行時(shí)異常燃乍,我們需要做到至少以下5個(gè)步驟:
檢查系統(tǒng)版本號(hào):針對(duì)6.0以下的系統(tǒng)版本唆樊,默認(rèn)權(quán)限在安裝的時(shí)候已經(jīng)獲取到了,對(duì)于6.0開始的版本刻蟹,才需要做運(yùn)行時(shí)的權(quán)限檢查逗旁。
檢查申請(qǐng)的權(quán)限:在使用某個(gè)權(quán)限之前,需要檢查權(quán)限是否已經(jīng)獲取到了舆瘪。
解釋申請(qǐng)的權(quán)限:在權(quán)限沒有獲取到的情況下片效,需要通過shouldShowRequestPermissionRationable()
的判斷來決定如何給用戶進(jìn)行提示。
執(zhí)行申請(qǐng)權(quán)限操作:前面判斷沒有獲取到權(quán)限英古,為了能夠讓功能順利執(zhí)行淀衣,我們會(huì)需要在代碼里面再次執(zhí)行申請(qǐng)此權(quán)限的操作。


處理權(quán)限申請(qǐng)的結(jié)果:申請(qǐng)權(quán)限之后哺呜,我們需要處理申請(qǐng)的響應(yīng)結(jié)果舌缤,分別處理權(quán)限申請(qǐng)成功與失敗的情況


4)使用MediaSessionCompat操作音樂的播放
MediaSessionCompat來自Android官方的兼容包,通過它可以告訴Android系統(tǒng)與其他的應(yīng)用某残,自己正在播放的內(nèi)容是什么以及自己支持哪些類型的播放控制:

在Android的官方培訓(xùn)課程中有介紹過關(guān)于Media Button Receiver的概念国撵,Android系統(tǒng)會(huì)把來自藍(lán)牙控制器或者是耳機(jī)等其他設(shè)備的操作事件轉(zhuǎn)換成Media Button事件傳遞出來,如果我們的應(yīng)用程序需要監(jiān)聽這些事件并做出相應(yīng)的響應(yīng)玻墅,就需要注冊(cè)MEDIA_BUTTON的action介牙,接收到這些事件之后,再傳遞給音樂播放模塊進(jìn)行控制處理澳厢。

基于上面的認(rèn)知环础,我們現(xiàn)在演示如何使用MediaSessionCompat,下面演示了如何構(gòu)造一個(gè)MediaSessionCompat以及構(gòu)造完之后通常需要做的三件事情:設(shè)置合理的flag剩拢,設(shè)置回調(diào)(在5.0開始會(huì)響應(yīng)onPlay线得,onPause等等回調(diào)),設(shè)置激活徐伐。
android_dev_patterns_media_usage

搭建好了MediaSessionCompat之后贯钩,還需要通過MediaMetadataCompat
來傳遞播放的資料信息,通過PlaybackStateCompat
來傳遞播放的狀態(tài)信息办素。

做了上面那些操作之后角雷,MediaSessionCompat的任務(wù)就算是完成了。

5)使用Toolbar替代ActionBar
自從MaterialDesign開始性穿,Android官方就開始使用Toolbar替代了原來的ActionBar勺三,現(xiàn)在Toolbar已經(jīng)加入Support兼容包。Toolbar是一個(gè)相比起ActionBar更加豐富需曾,更加靈活的組件狰闪,另外它的布局本身還是View Hierarchy的一部分,這就意味著可以對(duì)Toolbar執(zhí)行動(dòng)畫操作市埋,增加點(diǎn)擊滑動(dòng)事件等等谋旦,甚至我們還可以在一個(gè)頁面里面加入兩個(gè)Toolbar。
為了啟用Toolbar桑嘶,首先要做的事情就是關(guān)閉當(dāng)前Activity的ActionBar炊汹。我們可以通過使得Activity的主題繼承Theme.AppCompat.NoActionBar
,然后在對(duì)應(yīng)的XML布局文件中逃顶,添加類似下面的toolbar布局信息:

<!--Toolbar-->
<android.support.v7.widget.Toolbar 
android:id="@+id/toolbar_layout" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:layout_alignParentTop="true"
 android:minHeight="?attr/actionBarSize">
</android.support.v7.widget.Toolbar>```

在布局文件中添加Toolbar的信息之后讨便,需要啟動(dòng)Toolbar替代ActionBar,需要像下面一樣做設(shè)置:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_layout);
setSupportActionBar(toolbar);
}```

關(guān)于更多Toolbar的細(xì)節(jié)以政,請(qǐng)參考官方文檔https://developer.android.com/reference/android/support/v7/widget/Toolbar.html
6)使用AppBarLayout并處理滑動(dòng)手勢(shì)
AppBarLayout是一個(gè)在android.support.design兼容包(這里有關(guān)于該兼容包的官方博客介紹http://android-developers.blogspot.com/2015/05/android-design-support-library.html)里面的新推出的組件霸褒,它是一個(gè)垂直方向的LinearLayout,包裝了很多Material Design的設(shè)計(jì)元素盈蛮,例如滑動(dòng)手勢(shì)的處理废菱。我們可以使用app:layout_scrollFlags
這樣的標(biāo)簽來設(shè)置滑動(dòng)的行為表現(xiàn)。關(guān)于App Bar,官方還有這樣一段描述:


使用AppBarLayout需要注意下面幾個(gè)要點(diǎn):
首先殊轴,AppBarLayout必須作為CoordinatorLayout
的直接子View
其次衰倦,在AppBarLayout里面必須包含一個(gè)ToolBar
最后,在CoordinatorLayout里面可以添加那些可以滑動(dòng)的組件旁理,例如RecyclerView

一個(gè)標(biāo)準(zhǔn)的布局文件應(yīng)該是類似下面結(jié)構(gòu)的:



我們需要注意樊零,在Toolbar里面設(shè)置的layout_scrollFlags會(huì)影響到滑動(dòng)之后的顯示效果,請(qǐng)看下面的具體解釋:


android_dev_patterns_appbar_scroll_flag

7)使用SearchView來實(shí)現(xiàn)搜索功能
關(guān)于在使用搜索的時(shí)候及時(shí)顯示給用戶的候選詞孽文,會(huì)需要根據(jù)數(shù)據(jù)的類型以及具體的情況做不同的處理驻襟,這里先暫時(shí)不討論那一塊的內(nèi)容。

android_dev_patterns_searchview_tips

上面的圖示已經(jīng)清楚的演示了使用SearchView處理搜索的通常情況芋哭,關(guān)于如何實(shí)現(xiàn)這個(gè)功能沉衣,需要做到以下幾個(gè)步驟:
在Menu的XML文件中,聲明使用SearchView

在onCreateOptionsMenu的回調(diào)函數(shù)里面獲取到SearchView减牺,并設(shè)置監(jiān)聽(請(qǐng)注意使用MenuItemCompat的那行代碼厢蒜,否則會(huì)出現(xiàn)很多兼容性問題,獲取不到這個(gè)View等等奇怪的BUG)烹植,在監(jiān)聽回調(diào)里面處理業(yè)務(wù)邏輯


至此斑鸦,其實(shí)就已經(jīng)實(shí)現(xiàn)了一個(gè)基礎(chǔ)的搜索功能。但是草雕,如果為了能夠讓自己的應(yīng)用的某些功能被Android系統(tǒng)的Search功能檢索到巷屿,我們就需要做更進(jìn)一步的操作,例如定義Searchable墩虹,實(shí)現(xiàn)一個(gè)SearchableActivity嘱巾,響應(yīng)系統(tǒng)的Search行為等等。國內(nèi)的應(yīng)用很少會(huì)去關(guān)注這個(gè)功能诫钓,這里就不展開了旬昭,感興趣點(diǎn)擊下面的鏈接進(jìn)一步學(xué)習(xí):https://developer.android.com/guide/topics/search/index.html
8)Navigation Drawer, DrawerLayout, NavigationView
Navigation Drawer是Material Design當(dāng)中很重要的一種設(shè)計(jì)元素,為了能夠快速的實(shí)現(xiàn)這種設(shè)計(jì)菌湃,Android在新的design support包里面為我們提供了DrawerLayout與NavigationView问拘。

實(shí)現(xiàn)這樣的一個(gè)功能,我們需要在XML中寫下類似下面的布局文件

在NavigationView中有兩個(gè)重要的標(biāo)簽惧所,app:headerLayout與app:menu骤坐,分別代表了拉出菜單的頂部布局與下面的菜單項(xiàng)列表。創(chuàng)建菜單項(xiàng)列表下愈,可以使用類似下面的MenuItem文件:

android:checked
表示當(dāng)前選中的Item纽绍,會(huì)被系統(tǒng)Highlight出來。除了上面簡(jiǎn)單的平鋪的菜單势似,還可以使用菜單嵌套的方式實(shí)現(xiàn)多級(jí)的菜單拌夏。關(guān)于點(diǎn)擊具體某個(gè)菜單的時(shí)候的監(jiān)聽與響應(yīng)僧著,需要做如下的設(shè)置:

除了點(diǎn)擊菜單事件,我們還需要處理整個(gè)側(cè)滑菜單的打開與關(guān)閉事件障簿,當(dāng)我們給DrawerLayout設(shè)置了setDrawerListener之后霹抛,可以得到下面兩個(gè)回調(diào):

大多數(shù)時(shí)候,側(cè)滑菜單都是從左到右滑出的卷谈,但是我們也可以做到從右往左滑出,只需要在DrawerLayout的菜單布局LinearLayout里面修改一下margin的相關(guān)屬性即可:

9)Tabs and ViewPager

ViewPager是Android上面實(shí)現(xiàn)橫向滑動(dòng)的基礎(chǔ)組件霞篡,能夠幫助大家迅速搭建類似上面圖示一樣的左右滑動(dòng)交互設(shè)計(jì)世蔗。ViewPager需要使用PagerAdapter來提供內(nèi)容,除了PagerAdpater朗兵,Android還提供了FragmentPagerAdpater與FragmentStatePagerAdapter污淋,前者會(huì)把所有的fragment都保存在內(nèi)存中,以便提高切換速度余掖,后者僅僅保留了fragment狀態(tài)信息寸爆,fragment還是會(huì)進(jìn)行正常的重建與銷毀。一個(gè)典型的使用demo代碼如下:

為了實(shí)現(xiàn)前面圖示的Tab與ViewPager的綁定盐欺,我們可以使用Android Design Support Library提供的TabLayout
赁豆,僅僅需要按照下面的代碼示例一樣把TabLayout與ViewPager做一個(gè)綁定,就能夠?qū)崿F(xiàn)左右滑動(dòng)與點(diǎn)擊Tab快速切換的功能:

關(guān)于Material Design里面的Tabs設(shè)計(jì)冗美,請(qǐng)?jiān)賲⒖?a target="_blank" rel="nofollow">http://www.google.com/design/spec/components/tabs.html以及官方Training課程里面的http://developer.android.com/training/implementing-navigation/lateral.html
10)Making Apps Accessible
為了照顧部分視力或者聽覺不好的用戶魔种,我們需要做一定的處理使得自己的應(yīng)用能夠被每一個(gè)可用。Android系統(tǒng)為了幫助應(yīng)用實(shí)現(xiàn)輔助功能粉洼,提供了諸如文本朗讀节预,觸感反饋,指向炳導(dǎo)航属韧,手勢(shì)導(dǎo)航等等功能來更好的幫助用戶使用這些應(yīng)用安拟。

為了確保你的應(yīng)用能夠被Android系統(tǒng)提供的輔助功能正常使用,需要做以下三個(gè)步驟的檢查:
Content Description:確保類似ImageView宵喂,ImageButton糠赦,CheckBox等組件都包含了content descrption。

Focus Order:確保給布局里面的關(guān)鍵元素增加了Focus的指示順序锅棕,只有這樣愉棱,輔助功能才能夠在指向?qū)Ш降臅r(shí)候幫助用戶按照指定的順序來聚焦界面元素。


Feedback Mechanisms:確保部分關(guān)鍵的操作有多個(gè)反饋哲戚,例如當(dāng)短信來的時(shí)候奔滑,既有聲音也有震動(dòng),這樣才能夠確保聽力不好的用戶可以通過震動(dòng)的反饋來感知到響應(yīng)顺少。

更多關(guān)于輔助功能的知識(shí)朋其,請(qǐng)參考
http://developer.android.com/guide/topics/ui/accessibility/checklist.html

? 轉(zhuǎn)載自:胡凱--Android性能優(yōu)化典范 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末王浴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子梅猿,更是在濱河造成了極大的恐慌氓辣,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袱蚓,死亡現(xiàn)場(chǎng)離奇詭異钞啸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)喇潘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門体斩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人颖低,你說我怎么就攤上這事絮吵。” “怎么了忱屑?”我有些...
    開封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵蹬敲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我莺戒,道長(zhǎng)伴嗡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任从铲,我火速辦了婚禮闹究,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘食店。我一直安慰自己渣淤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開白布吉嫩。 她就那樣靜靜地躺著价认,像睡著了一般。 火紅的嫁衣襯著肌膚如雪自娩。 梳的紋絲不亂的頭發(fā)上用踩,一...
    開封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音忙迁,去河邊找鬼脐彩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛姊扔,可吹牛的內(nèi)容都是我干的惠奸。 我是一名探鬼主播,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼恰梢,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼佛南!你這毒婦竟也來了梗掰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤嗅回,失蹤者是張志新(化名)和其女友劉穎及穗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绵载,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡埂陆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了娃豹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焚虱。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖培愁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缓窜,我是刑警寧澤定续,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站禾锤,受9級(jí)特大地震影響私股,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恩掷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一倡鲸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧黄娘,春花似錦峭状、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至誓焦,卻和暖如春胆敞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杂伟。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來泰國打工移层, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赫粥。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓观话,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親越平。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匪燕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

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