Android 四大开发组件
目錄
一、Activity組件
??1、Activity 相關概念介紹
??2、Activity生命周期
? 3、Activity 啟動模式
(1)standard模式
(2)singleTop模式 (棧頂復用模式)
(3)singTask 模式(棧內單例模式)
??(4) singleInstance模式(堆內單例模式)
? ?4、Activity 之間相互跳轉及通信
(1)不帶數(shù)據(jù)跳轉
(2)帶數(shù)據(jù)或多個數(shù)據(jù)跳轉
(3)帶數(shù)據(jù)跳轉,帶數(shù)據(jù)返回
(4)Intent隱式實現(xiàn)啟動其他程序Activity
二、Service組件
?1、Service簡單介紹
?2、Service啟動的兩種方式
(1)startService()
(2)bindService()綁定服務
(3)實現(xiàn)前臺Service
(4)使用IntentService
三、Broadcast Receiver組件
1、簡單介紹
2、使用介紹
? ?(1)無序廣播的使用
? ?(2)有序廣播的使用
? ?(3)常用的系統(tǒng)廣播的action 和permission
???????四、內容提供者(Content Provider)組件
1、簡單介紹
2、使用
? ?(1)使用系統(tǒng)提供的內容提供器
Android四大組件分別為Activity、Service、Broadcast Receiver、Content Provider。
一、Activity組件
1、Activity 相關概念介紹
????????一個 Activity 包含了用戶能夠看到的界面,從而于用戶進行交互。一個應用程序中可以有零個或者多個Activity。零個 Activity 就表示,這個應用程序不包含與用戶交互的界面。
????????Android應用中每一個Activity都必須要在AndroidManifest.xml配置文件中聲明注冊,否則系統(tǒng)將不識別也不執(zhí)行該Activity。
<activityandroid:name=".LoginActivity"android:exported="true"android:label="@string/title_activity_login"android:launchMode="singleTop"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter> </activity>2、Activity生命周期
????????Android 是使用任務(task)來管理Activity的,一個任務就是一組存放在棧里Activity的集合,這個棧也叫作返回棧。
????????Activity的生命周期由以下幾個部分組成:
| 函數(shù) | 描述 |
| onCreat() | 一個Activity啟動后第一個被調用的函數(shù),常用來在此方法中進行Activity的一些初始化操作。例如創(chuàng)建View,綁定數(shù)據(jù),注冊監(jiān)聽,加載參數(shù)等。 |
| onStart() | 當Activity顯示在屏幕上時,此方法被調用但此時還無法進行與用戶的交互操作。 |
| onResume() | 這個方法在onStart()之后調用,也就是在Activity準備好與用戶進行交互的時候調用,此時的Activity一定位于Activity棧頂,處于運行狀態(tài)。 |
| onPause() | 這個方法是在系統(tǒng)準備去啟動或者恢復另外一個Activity的時候調用,通常在這個方法中執(zhí)行一些釋放資源的方法,以及保存一些關鍵數(shù)據(jù)。 |
| onStop() | 這個方法是在Activity完全不可見的時候調用的。 |
| onDestroy() | 這個方法在Activity銷毀之前調用,之后Activity的狀態(tài)為銷毀狀態(tài)。 |
| onRestart() | 當Activity從停止stop狀態(tài)恢進入start狀態(tài)時調用狀態(tài)。 |
????????????????
????????實際操作過程中,當打開啟動Android應用時,MainActivity會經(jīng)過onCreate -> onStart -> onResume三個階段,此時若按home鍵或則back按鍵,MainActivity會經(jīng)過onPause -> onStop這兩個階段,再進入此MainActivity時,會再調用onRestart -> onStart -> onResume三個階段。?
? 3、Activity 啟動模式
????????啟動模式一共有 4 中:standard、singleTop、singTask 和 singleInstance,可以在 AndroidManifest.xml 中通過 標簽指定 android:launchMode 屬性來選擇啟動模式。
? ? ?(1)standard模式
????????standard 模式是 Activity 的默認啟動模式,在不進行顯示指定的情況下,所有 Activity 都會自動使用這種啟動模式。對于使用 standard 模式啟動的 Activity,系統(tǒng)不會在乎這個 Activity 是否已經(jīng)存在在棧中了。每次啟動的時候都會創(chuàng)建一個新的實例。一般用于打開郵件之類的。
????????
(2)singleTop模式 (棧頂復用模式)
????????如果 Activity 指定為 singleTop,在啟動 Activity 的時候發(fā)現(xiàn)返回棧的棧頂已經(jīng)是該 Activity 了。則認為可以直接使用它,就不會再創(chuàng)建新的 Activity 實例了。因為不會創(chuàng)建新的 Activity 實例,所以 Activity 的生命周期就沒有什么變化了。假設你在當前的Activity中又要啟動同類型的Activity,此時建議將此類型Activity的啟動模式指定為SingleTop,能夠降低Activity的創(chuàng)建,節(jié)省內存!
????????一般用于登錄頁面,新聞詳情頁等。
????????
(3)singTask 模式(棧內單例模式)
????????singleTop 很好的解決了重復創(chuàng)建棧頂 Activity 的問題。如果 Activity 沒有處于棧頂?shù)奈恢?#xff0c;還是可能會創(chuàng)建多個 Activity 實例的。那就需要借助 singleTask 了。當 Activity 的啟動模式為 singleTask 的時候,每次啟動該 Activity 的時候系統(tǒng)會首先在返回棧中檢查是否存在該 Activity 的實例,如果發(fā)現(xiàn)已經(jīng)存在則直接使用該實例。并把這個 Activity 之上的所有 Activity 全部出棧,如果沒有就會創(chuàng)建一個新的 Activity 實例。
????????一般主頁面使用,購物頁面,付款頁面,瀏覽器主頁等。
????????
(4) singleInstance模式(堆內單例模式)
????????singleInstance 模式的 Activity 會啟用一個新的返回棧來管理這個 Activity 。在這種模式下會有一個單獨的返回棧來管理這個 Activity,不管是哪個應用程序來訪問這個 Activity,都共用的同一個返回棧,也就解決了共享 Activity 實例的問題。
????????
4、Activity 之間相互跳轉及通信
????????Intent(意圖)是應用程序種各個組件聯(lián)系的橋梁,通信的載體,負責應用程序中數(shù)據(jù)的傳遞。
(1)不帶數(shù)據(jù)跳轉
Intent intent = new Intent(this,MainActivity.class);startActivity(intent);????????此段代碼實現(xiàn)從當前Activity,跳轉到MainActivity,不帶任何參數(shù)。
(2)帶數(shù)據(jù)或多個數(shù)據(jù)跳轉
//帶數(shù)據(jù)跳轉 String data = "是我主活動調用了你"; Intent intent = new Intent(this, SecondActivity.class); intent.putExtra("ext", data); startActivity(intent);(3)帶數(shù)據(jù)跳轉,帶數(shù)據(jù)返回
Intent intent = new Intent(LoginActivity.this,RegisterActivity.class); Bundle bundle = new Bundle() ; bundle.putString("register","請開始注冊!"); intent.putExtras(bundle) ; startActivityForResult(intent,1);? ? ? ? 在跳轉時使用startActivityForResult方法,此方法傳入兩個參數(shù)一個是Intent ,另外一個是給當前請求設置的一個請求ID,此ID在結束數(shù)據(jù)時辨識是否使當前請求的返回結果。
????????同時要在跳轉源Activity中實現(xiàn) onActivityResult 方法來接收處理目的Activity返回的數(shù)據(jù)。
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case 1:if (resultCode == RESULT_OK) {final EditText loginUsername = findViewById(R.id.username);String returnUsername = data.getStringExtra("userName");//序列化方式取出實體User user = (User)data.getSerializableExtra("user");loginUsername.setText(returnUsername);loginUsername.setSelection(returnUsername.length());}break;default:} }(4)Intent隱式實現(xiàn)啟動其他程序Activity
? ? ? ? 在當前Activity中調用百度請求界面。
Uri uri = Uri.parse("https://www.baidu.com"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it);????????直接調用打電話功能
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:13207690000"));startActivity(i);????????在使用系統(tǒng)電話功能時需要給當前應用程序授權,在AndroidManifest.xml文件中增加
<uses-permission android:name="android.permission.CALL_PHONE" />?????????打開地圖界面
Uri uri = Uri.parse("geo:38.899533,-77.036476");Intent it = new Intent(Intent.ACTION_VIEW, uri);startActivity(it);二、Service組件
?1、Service簡單介紹
????????Service它可以在后臺執(zhí)行長時間運行操作而沒有用戶界面的應用組件,不依賴任何用戶界面,例如后臺播放音樂,后臺下載文件等。
????????雖然服務是在后臺運行的,但是Service和Activity都是運行在當前APP所在的main thread(UI主線程)中的,而耗時操作(如網(wǎng)絡請求、拷貝數(shù)據(jù)、大文件)會阻塞主線程,給用戶帶來不好的體驗。如果需要在服務中進行耗時操作,可以選擇 IntentService,IntentService是Service的子類,用來處理異步請求。
?2、Service啟動的兩種方式
(1)startService()
????????在Acitivity界面通過顯式意圖(或隱式意圖)的方式來啟動服務和關閉服務。
Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);startService(intentService);????????生命周期順序:onCreate->onStartCommand->onDestroy
????????onCreate()?當Service第一次被創(chuàng)建時調用。
????????onStartCommand()?當startService方法啟動Service時,該方法被調用。
????????onDestroy()?當Service不再使用時調用。
(2)bindService()綁定服務
????????當應用組件通過調用 bindService() 綁定到服務時,服務即處于“綁定”狀態(tài)。綁定服務提供了一個客戶端-服務器接口,允許組件與服務進行交互、發(fā)送請求、獲取結果。 僅當與另一個應用組件綁定時,綁定服務才會運行。 多個組件可以同時綁定到該服務,但全部取消綁定后,該服務即會被銷毀。
????????首先在我們的服務中創(chuàng)建一個內部類AudioBinder繼承Binder來獲取當服務實例,然后在onBind方法中返回當前服務的實例。
public class AudioServiceOnBind extends Service implements MediaPlayer.OnCompletionListener{private final IBinder binder = new AudioBinder();//用于播放音樂等媒體資源private MediaPlayer mediaPlayer;public AudioServiceOnBind() {super();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(AudioServiceOnBind.this.getClass().getName(),"執(zhí)行onStartCommand()");return 0;}@Overridepublic IBinder onBind(Intent intent) {return binder;}@Overridepublic void onCreate(){super.onCreate();Log.d(AudioServiceOnBind.this.getClass().getName(),"執(zhí)行onCreate()");if (mediaPlayer==null){mediaPlayer=MediaPlayer.create(this,R.raw.gumeng);mediaPlayer.setOnCompletionListener(this);}mediaPlayer.start();}@Overridepublic void onCompletion(MediaPlayer mp) {stopSelf();}@Overridepublic void onDestroy(){if(mediaPlayer.isPlaying()){mediaPlayer.stop();}mediaPlayer.release();stopForeground(true);Log.d(AudioServiceOnBind.this.getClass().getName(),"執(zhí)行onDestroy()");}//為了和Activity交互,我們需要定義一個Binder對象class AudioBinder extends Binder {//返回Service對象AudioServiceOnBind getService(){return AudioServiceOnBind.this;}}}????????然后在調用的Activity中創(chuàng)建一個ServiceConnection對象重寫其中的onServiceConnected方法獲取所要綁定的服務。在觸發(fā)事件的方法中調用bindService實現(xiàn)服務的最終綁定。
public class MainActivity extends AppCompatActivity {private AudioServiceOnBind audioServiceOnBind;//使用ServiceConnection來監(jiān)聽Service狀態(tài)的變化private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {audioServiceOnBind = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder binder) {//這里我們實例化audioService,通過binder來實現(xiàn)audioServiceOnBind = ((AudioServiceOnBind.AudioBinder) binder).getService();}};public void click_music_open(View view) {Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);bindService(intentService, conn, Context.BIND_AUTO_CREATE);} }????????生命周期:onCreate->onBind->onUnBind->onDestroy
????????onCreate()?當Service被創(chuàng)建時,由系統(tǒng)調用。
????????onBind()?當bindService方法啟動Service時,該方法被調用。
????????onUnbind()?當unbindService方法解除綁定時,該方法被調用。
????????onDestroy()?當Service不再使用時,由系統(tǒng)調用。
(3)實現(xiàn)前臺Service
????????Android 8.0 后系統(tǒng)不允許后臺應用創(chuàng)建后臺服務。 因此,Android 8.0 引入了一種全新的方法,即 Context.startForegroundService(),以在前臺啟動新服務。
在service onStartCommand方法中增加以下代碼
@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(AudioServiceOnBind.this.getClass().getName(),"執(zhí)行onStartCommand()");Intent nfIntent = new Intent(this, MainActivity.class);Notification.Builder builder = new Notification.Builder(this.getApplicationContext()).setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0)).setSmallIcon(R.mipmap.touxiang).setContentTitle("wu").setContentText("Android測試").setWhen(System.currentTimeMillis());String CHANNEL_ONE_ID = "com.wu";String CHANNEL_ONE_NAME = "Channel One";//安卓8.1以上系統(tǒng)NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);notificationChannel.enableLights(false);notificationChannel.setShowBadge(true);notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);manager.createNotificationChannel(notificationChannel);builder.setChannelId(CHANNEL_ONE_ID);Notification notification = builder.build();startForeground(1, notification);return super.onStartCommand(intent,flags,startId);}????????在調用Activity中調用startForegroundService方法。
public void click_music_open(View view) {Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {startForegroundService(intentService);} else {startService(intentService);}}(4)使用IntentService
????????由于Service中的邏輯都是執(zhí)行在主線程中的,此時如果在Service中處理一下耗時操作可能就會給用戶帶來不好的體驗。所以此時就可以使用Android多線程Service.
????????本質上IntentService是在Service里開啟線程去做任務處理。IntentService會在任務執(zhí)行完成后自行結束自己,而不需要外部去調用stopService了。
????????使用IntentService定義的服務,要開啟線程,只要重寫一個onHandleIntent()方法就可以了,而且在運行完之后會自動停止。
?????????例如數(shù)據(jù)下載 數(shù)據(jù)上傳等。
public class MyIntentService extends IntentService {private static final String TAG = "MyIntentService";public MyIntentService() {super("MyIntentService");}@Overrideprotected void onHandleIntent(Intent intent) {Log.d(TAG, "當前是子線程: " + Thread.currentThread().getId());//在這里實現(xiàn)異步多線程處理邏輯//例如數(shù)據(jù)下載 數(shù)據(jù)上傳等。Log.d(TAG, "我在后臺默默下載數(shù)據(jù)中。。。。");}@Overridepublic void onCreate() {Log.d(TAG, "onCreate: ");super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "onStartCommand: ");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {Log.d(TAG, "onDestroy: ");super.onDestroy();} }三、Broadcast Receiver組件
1、簡單介紹
????????廣播接收器是一個用于接收廣播信息,并做出對應處理的組件。比如我們常見的系統(tǒng)廣播:通知時區(qū)改變、電量低、用戶改變了語言選項等。
(1)有序廣播
????????只發(fā)送廣播到優(yōu)先級較高的接收者那里,然后由優(yōu)先級高的接收者決定是繼續(xù)傳播到優(yōu)先級低的接收者那里還是終止這個廣播。
(2)無序廣播
????????對于多個接收者來說是完全異步的,通常每個接收者都無需等待即可收到廣播,接收者相互之間不會有影響。對于這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。是我們使用較多的一種普通廣播類型。
(3)生命周期
????????BroadcastReceiver的生命周期從對象調用它開始,到onReceiver方法執(zhí)行完成之后結束。每次廣播被接收后會重新創(chuàng)建BroadcastReceiver對象,并在onReceiver方法中執(zhí)行完就銷毀,如果BroadcastReceiver的onReceiver方法中不能在10秒內執(zhí)行完成,Android會出現(xiàn)ANR異常。所以不要在BroadcastReceiver的onReceiver方法中執(zhí)行耗時的操作。
2、使用介紹
(1)無序廣播的使用
????????1、創(chuàng)建BreadcastReceiver的子類。
????????2、注冊BroadcastReceiver。
?????????靜態(tài)注冊
????????<!-- 在配置文件中注冊BroadcastReceiver能夠匹配的Intent -->
<receiverandroid:name=".MyReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.intent.action.MyReceiver"></action><category android:name="android.intent.category.DEFAULT"></category></intent-filter> </receiver>?????????動態(tài)注冊???????
MyReceiver receiver = new MyReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.MyReceiver"); registerReceiver(receiver, filter);???????(2)有序廣播的使用
????????接收者的創(chuàng)建和普通廣播一樣。有序和無序廣播區(qū)別在于可以實現(xiàn)廣播的攔截,高優(yōu)先級的接收者可以通過abortBroadcast()終止廣播。比如系統(tǒng)的接收短信廣播就是一個有序廣播,可以通過自定義的廣播進行攔截,只要設置的android:priority屬性,越大優(yōu)先級越高。這個值介于[-1000,1000]。
(2)有序廣播的使用 <receiverandroid:name="com.example.myapplication.MySecondReceiver"android:exported="true"><intent-filter android:priority="100"><action android:name="MY_BROADCAST"/></intent-filter> </receiver>????????注冊完廣播接收器后簡單實現(xiàn)一個廣播的發(fā)送器。?調用sendOrderedBroadcast方法進行有序廣播的發(fā)送。
Intent intent = new Intent(); intent.setAction("MY_BROADCAST"); intent.putExtra("msg", "你好廣播接收器,我是有序廣播"); intent.setPackage("com.example.myapplication"); sendOrderedBroadcast(intent, null);?????????發(fā)送完有序廣播后我們在自己定義的MySecondReceiver中實現(xiàn)接收到廣播的處理。
public class MySecondReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.i(MySecondReceiver.class.getName(),"我收到了廣播:" + intent.getStringExtra("msg"));Toast t = Toast.makeText(context,intent.getStringExtra("msg"),Toast.LENGTH_LONG);t.setGravity(Gravity.TOP,0,0);t.show();//可以選擇是否繼續(xù)廣播abortBroadcast();} }???????(3)常用的系統(tǒng)廣播的action 和permission
????????開機啟動
//開機啟動對應的Action <action android:name="android.intent.action.BOOT_COMPLETED"/> //開機啟動需要的授權 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />????????網(wǎng)絡狀態(tài)變化廣播
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>????????電量變化廣播
<action android:name="android.intent.action.BATTERY_CHANGED"/>???????四、內容提供者(Content Provider)組件
1、簡單介紹
????????Content Provider屬于Android應用程序的組件之一,作為應用程序之間唯一的共享數(shù)據(jù)的途徑,Content Provider主要的功能就是存儲并檢索數(shù)據(jù)以及向其他應用程序提供訪問數(shù)據(jù)的接口。
?????????Android內置的許多數(shù)據(jù)都是使用Content Provider形式,供開發(fā)者調用的(如視頻,音頻,圖片,通訊錄等)。
2、使用
(1)使用系統(tǒng)提供的內容提供器
????????Android系統(tǒng)中自帶的電話簿、短信、媒體庫等程序都提供了這樣的內容提供器供外界訪問。
????????每個應用程序要想訪問內容提供器中的數(shù)據(jù),就一定要借助ContentResolver類,可以通過Context中的getContentResolver方法來獲取。ContentResolver類提供了一系列方法用于對數(shù)據(jù)進行CRUD操作,insert方法用于添加數(shù)據(jù),update方法用于更新數(shù)據(jù),delete方法用于刪除數(shù)據(jù),query方法用于查詢數(shù)據(jù)。它和SQLiteDatabase很像,只不過它不接收表名,而是換成了Uri參數(shù)。
????????Uri包括兩部分:authority和path。authority命名為 包名.provider,path命名為 表名 ,所以一個標準的Uri可以為content://com.example.testspecial.provider/table1/1
????????獲取系統(tǒng)的手機聯(lián)系人
public class SecondActivity extends AppCompatActivity {private static final String TAG = "SecondActivity";private ContentResolver contentResolver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Objects.requireNonNull(getSupportActionBar()).hide();setContentView(R.layout.activity_second);Button bt_getPhone = (Button) findViewById(R.id.bt_getPhone);bt_getPhone.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {contentResolver = getContentResolver();if(ContextCompat.checkSelfPermission(SecondActivity.this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED){requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},1);}Cursor cursor=contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);while (cursor.moveToNext()){//獲得聯(lián)系人的idint _id=cursor.getInt(cursor.getColumnIndex("_id"));//獲得聯(lián)系人姓名String display_name=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));Log.i(TAG,"當前手機里的聯(lián)系人:" + _id+" 姓名:"+display_name + "電話號碼 "+number );}}});} }總結
以上是生活随笔為你收集整理的Android 四大开发组件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在 Mac 上映射网络驱动器
- 下一篇: 聊聊、Highcharts 动态数据