Android基礎(chǔ)知識總結(jié)
四大組件之一活動
活動狀態(tài)
- 運(yùn)行狀態(tài):活動處于棧頂
- 暫停狀態(tài):活動不處于棧頂旷偿,但仍然可見
- 停止?fàn)顟B(tài):完全不可見
- 銷毀狀態(tài):離開返回棧
生存期
- onCreate()
- onStart():不可見到可見調(diào)用
- onResume():與用戶進(jìn)行交互,處于棧頂運(yùn)行態(tài)
- onPause():準(zhǔn)備啟動或者恢復(fù)另一活動缔赠,
- onStop():完全不可見的時候調(diào)用
- onDestory():被銷毀之前調(diào)用,之后變?yōu)殇N毀狀態(tài)
- onRestart():這個方法由停止?fàn)顟B(tài)變?yōu)檫\(yùn)行狀態(tài)之前調(diào)用划鸽,也就是活動重新啟動了
當(dāng)Activity A到Activity B跳轉(zhuǎn)時如果此時內(nèi)存不夠丈冬,回收了A亮航,當(dāng)我們按返回鍵時仍然會回到A露氮,并且此時執(zhí)行的不是A的onRestart()。而是onCreate().為了保存數(shù)據(jù),我們可以回掉onSaveInstanceState()方法將數(shù)據(jù)放入bundle對象中掩宜,在onCreate()方法中有bundle參數(shù)進(jìn)行獲取
活動的啟動模式
在配置文件Activity中配置launchMode屬性
- standard 默認(rèn)
每次啟動一個新活動,它就會在返回棧中入棧握联,并處于棧頂位置。如果我們在一個Activity中跳轉(zhuǎn)自己嫡秕。點(diǎn)擊兩次創(chuàng)建之后,我們需連按三次Back建才能退出程序雳锋。 - singleTop
解決了默認(rèn)情況下秸应,在棧頂還要創(chuàng)建不合理榜跌。也就是如果Activity處于棧頂不創(chuàng)建,不處于棧頂就會重新創(chuàng)建。 - singleTask
解決一個棧中有多個Activity實(shí)例熔吗,也就是如果發(fā)現(xiàn)已經(jīng)存在棧中就把這活動之上的統(tǒng)統(tǒng)出棧,沒有則創(chuàng)建 - singleInstance
指定為該模式的活動會啟動一個新的返回棧來管理這個活動晒他。
四大組件之二廣播
- 標(biāo)準(zhǔn)廣播:異步執(zhí)行的廣播
- 有序廣播:同步執(zhí)行的廣播(對于廣播接收器是有先后順序)
接收系統(tǒng)廣播
動態(tài)注冊監(jiān)聽網(wǎng)絡(luò)變化
- 在代碼中注冊為動態(tài)注冊
- 在AndroidManifest.xml文件中注冊時靜態(tài)注冊
首先需要創(chuàng)建廣播接收器
我們只需要新建一個類讓它繼承BroadcastReceiver疟丙,并重寫父類的onReceive()(有廣播來時,這個方法會得到執(zhí)行)方法就行了舔清。具體邏輯這個方法中處理丝里,注意不能寫耗時操作要不然anr異常可柿,如果需要我們可以啟動一個服務(wù)Service,不要使用新線程完成丙者。因?yàn)閺V播接收器的生命周期很短复斥。可能出現(xiàn)子線程還沒有結(jié)束械媒,廣播解釋器已經(jīng)退出了目锭。
- 發(fā)送廣播:
- 創(chuàng)建一個IntentFilter 實(shí)例。并給他添加一個action如:android.net.com.CONNECTIVITY_CHANGE(網(wǎng)絡(luò)發(fā)生變化的廣播)纷捞,
- 創(chuàng)建一個NetworkChangeReceiver(自定義的廣播接收器類)的實(shí)例痢虹。
- 調(diào)用registerReceiver()方法進(jìn)行注冊。將兩個實(shí)例傳進(jìn)去主儡。
- 最后記得動態(tài)注冊廣播接收器一定要取消注冊才行奖唯。在onDestory()方法中調(diào)用unregisterReceiver()方法來實(shí)現(xiàn)。
靜態(tài)注冊(實(shí)例:實(shí)現(xiàn)開機(jī)啟動)
動態(tài)注冊廣播很靈活但是存在缺點(diǎn):必須要程序在啟動之后才能接受到廣播糜值。因?yàn)樽赃壿嬍菍懺趏nCreate()方法中丰捷。所以有靜態(tài)注冊
- 首先我們自定義一個廣播接收器:定義一個類BootCompleteReceiver繼承BroadcastReceiver。重寫onReceiver()方法寂汇。里面寫個Toast()打印String病往。
- 在AndroidManifest.xml中將這個廣播接收器類名進(jìn)行注冊。
- 新建一個<receiver>標(biāo)簽骄瓣,通過android:name來指定注冊哪一個廣播接收器停巷,然后在<intent-filter>標(biāo)簽加入想要接收的廣播就行了。
- Android系統(tǒng)啟動完成后發(fā)出一條值為:android.intent.action.BOOT_COMPLETED的廣播榕栏。因此將這個添加到<intent-filter>的<action>
- 這里還需要一個權(quán)限:android.permission.RECEIVE_BOOT_COMPLETED權(quán)限畔勤。
發(fā)生自定義廣播
發(fā)送標(biāo)準(zhǔn)廣播
發(fā)送廣播之前先定義一個廣播接收器,并且進(jìn)行注冊扒磁。action("com.zts.broadcast.MY_BROADCOAST");
我們定義一個Button作為發(fā)送廣播的觸發(fā)點(diǎn)庆揪。
-
在監(jiān)聽事件中調(diào)用
Intent intent=new Intent("com.zts.broadcast.MY_BROADCOAST"); sendBroadcast(intent);
由于廣播是使用intent進(jìn)行傳遞的,因此我們可以在intent中攜帶數(shù)據(jù)傳遞給廣播接收器
發(fā)送有序廣播
- 發(fā)送有序廣播我們只需要改動一行代碼渗磅,即將sendBroadcast()方法改成sendOrderedBroadcast(intent,null)
- 這個時候廣播接收器就有先后順序了嚷硫,而且前面的廣播接收器還可以將廣播截?cái)啵柚蛊淅^續(xù)傳播始鱼。
- 設(shè)置廣播接收器的先后順序
- 在intent—filter標(biāo)簽中設(shè)置屬性android:priority=100意思是優(yōu)先級設(shè)成了100
- 獲得了廣播的優(yōu)先權(quán),我們可以阻止繼續(xù)傳播脆贵,在onReceive方法中調(diào)用:abortBroadcast();
android.intent.action.TIME_SET:系統(tǒng)時間被修改医清。
android.intent.action.DATE_CHANGED:系統(tǒng)日期被修改。
android.intent.action.BOOT_COMPLETED:系統(tǒng)啟動完成卖氨。
android.intent.action.BATTERY_CHANGED:設(shè)備電量改變会烙。
android.intent.action.BATTERY_LOW:設(shè)備電量低负懦。
android.intent.action.ACTION_POWER_CONNECTED:設(shè)備連接電源。
android.intent.action.ACTION_POWER_DISCONNECTED:設(shè)備斷開電源柏腻。
android.provider.Telephony.SMS_RECEIVED:系統(tǒng)收到短信纸厉。
android.intent.action.NEW_OUTGOING_CALL:撥打電話。
android.intent.action.SCREEN_OFF當(dāng)屏幕鎖屏的時候觸發(fā)
android.intent.action.SCREEN_ON屏幕解鎖的時候觸發(fā)
android.intent.action.USER_PRESENT當(dāng)用戶重新喚醒手持設(shè)備時觸發(fā)
ACTION_TIME_CHANGED:系統(tǒng)時間被改變
ACTION_TIMEZONE_CHANGED:系統(tǒng)時區(qū)被改變
ACTION_BOOT_COMPLETED:系統(tǒng)啟動完成
ACTION_PACKAGE_ADDED:系統(tǒng)添加包
ACTION_PACKAGE_CHANGED:系統(tǒng)的包改變
ACTION_PACKAGE_REMOVED:此外的包被刪除
ACTION_PACKAGE_RESTARTED:系統(tǒng)的包被重啟
ACTION_PACKAGE_DATA_CLEARED:系統(tǒng)的包數(shù)據(jù)被清空
ACTION_SHUTDOWN:系統(tǒng)被關(guān)閉
使用本地廣播
為了簡單解決廣播安全性問題(自己廣播被攔截五嫂,或垃圾廣播)颗品。LocalBroadcaseManager()
-
我只需要先獲得這個管理類
LocalBroadcastManager localBroadcastManager=LocalBroadcastManager.getInstance(this);
發(fā)生廣播時用這個對象發(fā)送即可
localBroadcastManager.sendBroadcast(intent);
注冊和取消注冊同樣也是用這個對象去調(diào)用相應(yīng)的方法
本地廣播是無法通過靜態(tài)注冊方式去接收的。他的優(yōu)勢:
- 廣播在我們程序內(nèi)部沃缘,不必?fù)?dān)心機(jī)密數(shù)據(jù)泄露
- 其他的程序無法將廣播發(fā)送到我們內(nèi)部
- 發(fā)生本地廣播比起發(fā)送系統(tǒng)全局廣播將會更加高效
四大組件之三服務(wù)
服務(wù)的基本用法
定義一個服務(wù)
新建一個MyService的類躯枢,并讓他繼承Service此時要重寫onBind()方法,我們可以重寫如下方法:
onCreate():在服務(wù)創(chuàng)建的時候調(diào)用
onStartCommand()方法會在每次服務(wù)啟動的時候調(diào)用
onDestory()方法會在服務(wù)銷毀的時候調(diào)用(回收不再使用的資源)
-
需要在AndroidManifest.xml文件中注冊才能生效
<service android:name=".MyService"></service>
啟動和停止服務(wù)
主要也是借助Intent來實(shí)現(xiàn)的
-
啟動服務(wù)
startService(new Intent(this,MyService.class))
-
停止服務(wù)
stopService(new Intent(this,MyService.class))
如果我們想要讓服務(wù)自己停止下來槐臀,只需要在MyService的任何一個位置調(diào)用stopSelf()方法就能讓這個服務(wù)停止下來
服務(wù)和活動之間通信
為了讓服務(wù)和活動更加緊密一點(diǎn)锄蹂。
首先在Activity中創(chuàng)建一個ServiceConnection的匿名類,在里面重寫了OnServiceConnected()方法和onServiceDisconnected()方法水慨。
-
綁定服務(wù)我們調(diào)用的是(BIND_AUTO_CREATE表示活動和服務(wù)進(jìn)行綁定后自動創(chuàng)建服務(wù))
bindService(intent,connection,BIND_AUTO_CREATE);
-
解除綁定
unbindService(connection)
這個時候要用到的是onBind()方法得糜。這里返回的對象會在onServiceDisconnected()這個第二參數(shù)中,
服務(wù)的生命周期
- onCreate() 服務(wù)之前沒有創(chuàng)建過就會先執(zhí)行
- onStartCommand()方法執(zhí)行每次調(diào)用startService()就會執(zhí)行晰洒。但是還是只存在一個實(shí)例
- onBind():在Context的bindService()調(diào)用時就會執(zhí)行該方法
- onDestory(): 調(diào)用startService后再調(diào)用stopService()時就會執(zhí)行掀亩,調(diào)用bindService 后又調(diào)用unbindService()也會執(zhí)行
當(dāng)調(diào)用了startService()又調(diào)用bindService()此時只有當(dāng)兩個同時調(diào)用stopService和unbindService().onDestory()才會執(zhí)行。
使用前臺服務(wù)
前臺服務(wù)和普通服務(wù)最大的區(qū)別在于欢顷,它會一直有一個正在運(yùn)行的圖標(biāo)在系統(tǒng)狀態(tài)欄顯示槽棍,下拉狀態(tài)欄后可以看到更加詳細(xì)的信息,非常類似于通知的效果抬驴。比如:墨跡天氣炼七,它的服務(wù)后臺更新天氣數(shù)據(jù)的同時,還會在系統(tǒng)狀態(tài)欄一直顯示當(dāng)前的天氣信息
IntentService
Android中的Service是用于后臺服務(wù)的布持,當(dāng)應(yīng)用程序被掛到后臺的時候豌拙,
為了保證應(yīng)用某些組件仍然可以工作而引入了Service這個概念,
那么這里面要強(qiáng)調(diào)的是Service不是獨(dú)立的進(jìn)程题暖,也不是獨(dú)立的線程按傅,
它是依賴于應(yīng)用程序的主線程的,也就是說胧卤,在更多時候
不建議在Service中編寫耗時的邏輯和操作唯绍,否則會引起ANR(Application Not Responding)。
那么我們當(dāng)我們編寫的耗時邏輯枝誊,不得不被service來管理的時候况芒,
在Service啟動一個新子線程,在子線程完成耗時操作叶撒。
就需要引入IntentService
- IntentService是繼承Service的绝骚,那么它包含了Service的全部特性耐版,當(dāng)然也包含service的生命周期,
- 那么與service不同的是压汪,IntentService在執(zhí)行onCreate操作的時候粪牲,內(nèi)部開了一個線程
- 去你執(zhí)行你的耗時操作。該線程保證同一時刻只處理一個Intent.這樣IntentService不會阻塞主線程止剖。
- IntentService的使用和Service是類似腺阳。它需要重寫
onHandleIntent(Intent intent)方法。
內(nèi)容提供器Content Provider
內(nèi)容提供器簡介
當(dāng)系統(tǒng)部署多個Android應(yīng)用之后滴须,有時候就需要在不同的應(yīng)用之間共享數(shù)據(jù)舌狗,比如現(xiàn)在有一個短信接收應(yīng)用,用戶想把接收到的陌生短信的發(fā)信人添加到聯(lián)系人管理應(yīng)用中扔水,就需要不同應(yīng)用之間共享數(shù)據(jù)痛侍。對于這種需要在不同應(yīng)用之間共享數(shù)據(jù)的需求,可以讓一個應(yīng)用程序直接去操作另外一個應(yīng)用程序所記錄的數(shù)據(jù)
1 比如操作它所記錄的SharedPreferences魔市,文件
或數(shù)據(jù)庫等主届。這種方式顯得太雜亂了。
2 不同
應(yīng)用程序記錄數(shù)據(jù)的方式差別很大待德,這種方式
不利于應(yīng)用程序之間進(jìn)行數(shù)據(jù)交換君丁。
為了在應(yīng)用程序之間交換數(shù)據(jù),Android提供
了ContentProvider,ContentProvider是不同應(yīng)用程序之間進(jìn)行數(shù)據(jù)交換的標(biāo)準(zhǔn)API将宪,
當(dāng)一個應(yīng)用程序需要把自己的數(shù)據(jù)暴露給其他程序使用時绘闷,
該應(yīng)用程序就可通過提供ContentProvider來實(shí)現(xiàn),其他應(yīng)用程序可通過ContentResolver
來操作ContentProvider暴露的數(shù)據(jù)较坛,
包括增加數(shù)據(jù)
刪除數(shù)據(jù)
修改數(shù)據(jù)
-
查詢數(shù)據(jù)等印蔗。
ContentProvider也是Android應(yīng)用的四大組件之一,需要在AndroidManifest.xml文件中進(jìn)行配置.
Android已經(jīng)為常見的一些數(shù)據(jù)提供了默認(rèn)的ContentProvider.
比如說短信丑勤,電話华嘹,多媒體等 開發(fā)ContentProvider
:定義自己的ContentProvider類,該類繼承ContentProvider基類
-
:暴露ContentProvider提供的數(shù)據(jù)
* 重寫onCreate():該方法在ContentProvider創(chuàng)建后被調(diào)用- 重寫getType():該方法用于返回當(dāng)前Uri所代表的數(shù)據(jù)的MIME類型,
如果該Uri對應(yīng)的數(shù)據(jù)可能包括多條記錄法竞,那么MIME類型
字符串應(yīng)用以vnd.android.cursor.dir/開始
如果該Uri對應(yīng)的數(shù)據(jù)只包括一條記錄耙厚,那么MIME類型
字符串應(yīng)用以vnd.android.cursor.item/開始 - 重寫insert(Uri,ContentValue values):根據(jù)Uri插入values對應(yīng)的數(shù)據(jù)
- 重寫delete(Uri,String selection,String[] selectArgs):根據(jù)Uri刪除select條件匹配的全部記錄
- 重寫update():根據(jù)Uri修改select條件所匹配的全部記錄
- 重寫query():根據(jù)Uri查詢出select條件所匹配的全部記錄
注意:重寫的這些方法并不是給該應(yīng)用本身調(diào)用的,
而是供其他應(yīng)用來調(diào)用岔霸。 - 重寫getType():該方法用于返回當(dāng)前Uri所代表的數(shù)據(jù)的MIME類型,
第三步:在AndroidManifest.xml文件中注冊該ContentProvider,
指定android:authorities屬性
<provider android:name=""
authorities=""
android:exported/>-
.Uri:用于表示這個ContentProvider所提供的數(shù)據(jù)
Uri:統(tǒng)一資源標(biāo)識符 --URL:統(tǒng)一資源定位符 --URN:統(tǒng)一資源命名符 如:http://www.baidu.com/index.html http:// 是URL的協(xié)議部分,是固定的 www.baidu.com是域名部分薛躬,是固定的 index.html是網(wǎng)站資源部分,是動態(tài)的
而ContentProvider提供的Uri秉剑,例如:
如:content://com.briup.dictprovider/users
content://是Uri的協(xié)議部分泛豪,暴露ContentProvider,訪問
contentProvider的協(xié)議默認(rèn)是content://,這個部分是固定的侦鹏。
com.briup.dictprovider:是ContentProvider的authority诡曙。
系統(tǒng)就是由這個部分找到操作哪個ContentProvider.
只要訪問指定的ContentProvider,這個部分總是固定的。
users:是資源部分略水,當(dāng)訪問者需要訪問不同資源時价卤,
這個部分是動態(tài)改變的。
Uri提供了parse()靜態(tài)方法渊涝,可以將字符串轉(zhuǎn)換為Uri:
Uri uri = Uri.parse("content://com.briup.dictprovider/user/2");
- .ContentResolver
通過ContentResolver來操作ContentProvider所暴露的數(shù)據(jù)
使用步驟:
第一步通過Context中獲取ContentResolver對象:getContentResolver()
第二步調(diào)用ContentResolver中相應(yīng)的方法:
insert,delete,update,query
原理:
A應(yīng)用:提供數(shù)據(jù) ContentProvider
^
|
|
Uri
^
|
|
B應(yīng)用: 獲取數(shù)據(jù)ContentResolver
當(dāng)B應(yīng)用調(diào)用ContentResolver的insert方法時
實(shí)際上相當(dāng)于調(diào)用了該Uri對應(yīng)的ContentProvider(屬于A應(yīng)用)的insert方法
當(dāng)B應(yīng)用調(diào)用ContentResolver的update方法時慎璧,實(shí)際上相當(dāng)于調(diào)用了
該Uri對應(yīng)的ContentProvider(屬于A應(yīng)用)的update方法。
在A應(yīng)用編寫ContentProvider跨释,
- 重寫onCreate(),getType(),insert(),delete(),update(),query()
- 在Manifest中配置<provider />標(biāo)簽
android:name provider的全類名
android:authorities 為該P(yáng)rovider設(shè)置訪問URI的Host部分
android:exported 設(shè)置該P(yáng)rovider可以被其他應(yīng)用程序訪問
在B應(yīng)用
- 調(diào)用getContentResolver胸私,獲取resolver對象
- 調(diào)用insert(),delete(),update(),query(),傳入U(xiǎn)RI實(shí)現(xiàn)數(shù)據(jù)訪問