《瞭解Android四大元件 》的補充
Activity
View元件是所有UI控制元件、容器控制元件的基類,View元件就是Android應用中使用者實實在在看到的部分。但View元件需要放到容器元件中,或者使用Activity將它顯示出來。如果需要通過某個Activity把指定的View顯示出來,呼叫Activity的setContentView()方法即可。
- 接受一個View物件作為引數
如: LinearLayout layout = new LinearLayout(this);
setContentView(layout);
- 接受一個佈局管理資源的ID作為引數
如: setContentView(R.layout.main);
其他知識,在《瞭解Android四大元件》中,有詳細完整的講解,並已經親測
Service
關於Activity和Service的選擇標準的一些事:
如果某個程式元件需要在執行時向用戶呈現某種介面,或者該程式需要與使用者互動,就需要使用Activity;否則就應該考慮使用Service
動手試試看
建立、配置Service
就如activity一樣,對於Service的開發也需要兩個步驟:
- 定義一個繼承Service的子類
- 在AndroidManifest.xml檔案中配置該Service
具體的需要被覆蓋的主要方法的詳解在《瞭解Android四大元件中》,在這裡直接上原始碼:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class FirstService extends Service
{
// 必須實現的方法
@Override
public IBinder onBind(Intent arg0)
{
return null;
}
// Service被建立時回撥該方法
@Override
public void onCreate()
{
super.onCreate();
System.out.println("Service is Created");
}
// Service被啟動時回撥該方法
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
System.out.println("Service is Started");
return START_STICKY;
}
// Service被關閉之前回調
@Override
public void onDestroy()
{
super.onDestroy();
System.out.println("Service is Destroyed");
}
}
在AndroidManifest.xml檔案中增加如下配置片段來配置Service:
<service android:name=".FirstService">
</service>
與配置Activity相似,配置Service時也可為<service.../>元素
配置<intent-filter.../>子元素,
用於說明該Service可被那些Intent啟動
啟動和停止Service
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button start, stop;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 獲取程式介面中的start、stop兩個按鈕
start = (Button) findViewById(R.id.start);
stop = (Button) findViewById(R.id.stop);
// 建立啟動Service的Intent
final Intent intent = new Intent(this , FirstService.class);
start.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
// 啟動指定Service的關鍵就是呼叫Context裡定義的startService
startService(intent);
}
});
stop.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
// 停止指定Service關鍵就是呼叫Context裡定義的stopService
stopService(intent);
}
});
}
}
效果演示:(Logcat)
當按下“START”按鈕時:
當按下”STOP”按鈕時:
嘗試連按三下“START”
我們可以發現,我們成功實現了FirstService中的被覆蓋的方法,並打印出想要的字,有一點值得注意:在效果圖三種,我們發現每次Service被啟動時都會回撥onStratCommond()方法,但多次啟動一個已有得Service元件將不會回撥onCreat()方法。
雖然這個Service幾乎什麼都沒幹,只是列印了幾行字而已,但是它是Service元件的框架,若想讓這個Service多做一些事,只需要在被覆蓋的onCreate() onStartCommand() onDestroy()的方法體中,實現相應的程式碼塊即可
BroadcastReceiver
啟動BroadcastReceiver的步驟
- 建立需要啟動的BroadcastReceiver的Intent
- 呼叫Context的sendBroadcast()或sendOrderedBroadcast()方法啟動指定的BroadcastReceiver
與OnXxxListener的區別
OnXxxListener只是程式級別的監聽器,這些監聽器執行在指定程式所在程序中,當程式退出時,OnXxxListener監聽器也就隨之關閉了。
但BroadcastReceiver是系統級別的監聽器,擁有自己的程序,只要存在與之匹配的Inten被廣播出來,BroadcastReceiver就會被激發。
如何指定BroadcastReceiver能匹配的Intent
使用程式碼進行指定,呼叫BroadcastReceiver的Context的registerReceiver(BroadcastReceiver receiver,IntentFilter filter)方法指定。
在AndroidManifest.xml檔案中配置。
**注意:**BroadcastReceiver的onReceive()方法不能再10秒內執行完成,Android會認為該程式無響應,故不要在此執行耗時的操作。(如果確實需要根據Broadcast來完成一項比較耗時的操作,則可以考慮通過Intent啟動一個Service來完成該操作)
動手試試傳送廣播
首先在activity_main.xml中建立一個用於傳送的按鈕(基本操作,程式碼就不放上來了)。
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button send;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 獲取程式介面中的按鈕
send = (Button) findViewById(R.id.send);
send.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
/*
*建立一個Intent物件,並使用該Intent物件對外發送一條廣播
*/
// 建立Intent物件
Intent intent = new Intent();
// 設定Intent的Action屬性
intent.setAction("org.crazyit.action.CRAZY_BROADCAST");
intent.putExtra("msg", "簡單的訊息");
// 傳送廣播
sendBroadcast(intent);
}
});
}
}
當符合該MyReceiver的廣播出現時,該MyReceiver的onReceiver()方法將會被出發,從而在該方法中顯示廣播所攜帶的資訊。
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context,
"接收到的Intent的Action為:" + intent.getAction()
+ "\n訊息內容是:" + intent.getStringExtra("msg")
, Toast.LENGTH_LONG).show();
}
}
因為上面廣播所用的Intent的Action為org.crazyit.action.CRAZY_BROADCAST,這就需要配置上面的BroadcastReceiver應監聽Action為該字串的Intent,在AndroidMainifest.xml檔案中增加程式碼塊
<receiver android:name=".MyReceiver">
<intent-filter>
<!-- 指定該BroadcastReceiver所響應的Intent的Action -->
<action android:name="org.crazyit.action.CRAZY_BROADCAST" />
</intent-filter>
</receiver>
點選“send”Button按鈕效果圖:
這裡演示的是使用者傳送的廣播,需要明白BroadcastReceiver還有一個重要的用途:接受系統廣播訊息。
其他這裡未寫到的內容見《瞭解Android四大元件》一文。
ContentProvider
在《瘋狂Android講義》中,有如下類比幫助我們理解ContentProvider、ContentResolver兩個核心API的作業。
把ContentProvider當做Android系統內部的“網站”,這個網站以固定的Uri對外提供服務;而ContentResolver則可當成Android系統內部的HttpClient,它可以向指定Uri傳送“請求”(實際上是呼叫ContentResolver的方法),這種請求最後委託給ContentProvider處理,從而實現對“網站”(即ContentProvider)內部資料進行操作。
ContentProvider只有一個onCreate()生命週期方法——當其他應用通過ContentResolver第一次訪問該ContentProvider時,onCreate()方法將會被回撥,onCreate()方法只會被呼叫一次;ContentProvider提供的query(),insert(),update()和delete()方法則由其他應用通過ContentResolver呼叫
那如何開發一個ContentProvider呢?
- 定義自己的ContentProvider類,該類需要繼承Android提供的ContentProvider基類。
- 在Androidmanifest.xml檔案中註冊這個ContentProvider,註冊時也需要為它繫結一個Uri