編輯:關於Android編程
簡介:
基本概念:Service是Android四大組件之一,運行在後台執行耗時操作並且不提供用戶界面。其他組件(如Activity)可以通過startService啟動該組件,也可以通過bindService啟動並綁定該組件進行通信。
使用場景:後台下載文件,播放音樂等。
注意:Service運行在主線程中,它不會創建屬於自己的線程,也不是運行在獨立的線程中,所以,在使用的時候,需要自己創建線程,而不應該直接執行耗時操作,這樣會引起ANR(程序未響應)錯誤。
Service的兩種形式:
Started Service
基本概念:其他組件(如Activity)通過調用startService()啟動該Service。擁有獨立的生命周期,不依賴啟動它的組件。
Bound Service
基本概念:其他組件為了與Service建立一個長時間的連接,通過調bindService啟動並綁定該Service。並能與之交互(發送請求,接受響應)。生命周期依賴綁定它的組件,可以是多個組件綁定同一個Service,一旦所有綁定它的組件取消綁定,則消亡。
Service的生命周期:
Started Service,Bound Service生命周期方法流程:

以下示例代碼包含兩個子Demo,所以第一個界面裡面包含兩個ListViewItem,分別可以進入這兩個子Demo:
public class MainActivity extends Activity {
private String[] datas = { "Started Service Demo", "Bound Service Demo" };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupViews();
}
private void setupViews() {
//新建一個數組適配器
ArrayAdapter arrayAdapter = new ArrayAdapter(
MainActivity.this, android.R.layout.simple_list_item_1, datas);
//獲取到ListView控件
ListView mListView = (ListView) findViewById(R.id.list_view_main);
//為ListView設置適配器
mListView.setAdapter(arrayAdapter);
//為ListView Item設置點擊監聽器
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view,
int position, long id) {
switch (position) {
case 0:
//跳轉到Started Service Demo Activity
redirectTOActivity(StartedServiceDemoActivity.class);
break;
case 1:
//跳轉到Bound Service Demo Activity
redirectTOActivity(BoundServiceDemoActivity.class);
break;
default:
break;
}
}
});
}
//跳轉到其他Activity
private void redirectTOActivity(Class destination){
Intent intent = new Intent(MainActivity.this, destination);
startActivity(intent);
}
}

以下是用StartService方法啟動Service的Activity:
//操作Servie01的Activity
public class StartedServiceDemoActivity extends Activity implements OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_started_service_demo);
setupViews();
}
private void setupViews() {
//設置兩個按鈕的監聽器為當前Activity
findViewById(R.id.button01).setOnClickListener(this);
findViewById(R.id.button02).setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent(StartedServiceDemoActivity.this, Service01.class);
int id = v.getId();
switch (id) {
case R.id.button01:
//Start Service按鈕被點擊
//啟動Service01
startService(intent);
break;
case R.id.button02:
//Stop Service按鈕被點擊
//停止Service01
stopService(intent);
break;
default:
break;
}
}
}

以下是Service01的內容,它的onBind()和onUnBInd()不會被回調:
/**
*
* Service01是以StartService方式啟動,以StopService方式停止的Service
* 如果當前無Service01實例,那麼回調方法onCreate()、onStartCommand()、onStart()方法會被依次調用
* 如果當前有Service01實例,那麼回調方法onStartCommand()、onStart()方法會被依次調用
*
*/
public class Service01 extends Service{
@Override
public IBinder onBind(Intent intent) {
System.out.println("Service01 onBind.....");
return null;
}
@Override
public void unbindService(ServiceConnection conn) {
System.out.println("Service01 onUnBind.....");
super.unbindService(conn);
}
@Override
public void onCreate() {
System.out.println("Service01 onCreate.....");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("Service01 onStartCommand.....");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(Intent intent, int startId) {
System.out.println("Service01 onStart.....");
}
@Override
public void onDestroy() {
System.out.println("Service01 onDestroy.....");
super.onDestroy();
}
}
public class BoundServiceDemoActivity extends Activity implements OnClickListener {
//實例化一個ServiceConnection的匿名子類對象
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
//當解除綁定事件發生時,此方法被回調
isBind = false;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//當綁定事件發生時,此方法被回調
MyBinder myBinder = (MyBinder) service; //進行一個類型轉換,得到MyBinder實例
//得到Service02實例
mService = myBinder.getService();
isBind = true;
}
};
//定義一個Servie02類型的實例
private Service02 mService = null;
//定義一個bool變量,記錄當前Activity是否綁定了Servie02
private boolean isBind = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bound_service_demo);
setupViews();
}
private void setupViews(){
findViewById(R.id.button01).setOnClickListener(this);
findViewById(R.id.button02).setOnClickListener(this);
findViewById(R.id.button03).setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent(BoundServiceDemoActivity.this, Service02.class);
int id = v.getId();
switch (id) {
case R.id.button01:
//開始綁定
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.button02:
//調用Service02的業務方法
if(mService != null){
int x = mService.getRandomNumber();
Toast.makeText(BoundServiceDemoActivity.this, "" + x, Toast.LENGTH_SHORT).show();
}
break;
case R.id.button03:
//解除當前Activity與Service02之間的綁定關系
unbindService(serviceConnection);
break;
default:
break;
}
}
}

以下是Service02的內容,它的onStart()和onStartCommand()方法不會被回調,
這種Service它一般去編寫的時候分為四個步驟,必須要有一個Binder實例來傳遞Service實例,具體如下:
/**
*
* Service02是以BindService方式啟動,以UnBindService方式解綁Service與組件之間的綁定關系,
* 如果Service02已經綁定啟動了,可以有其他的多個Activity通過BindService方式繼續與其綁定,只有
* 當所有的Activity都與Service02解除綁定關系,Service02實例才消亡
*
* 如果當前無Service02實例,那麼回調方法onCreate()、onBind()方法會被依次調用
* 如果當前有Service02實例,那麼回調方法onBind()方法會被依次調用
* 如果所有綁定Service02實例的組件都調用UnBind方法,那麼回調方法onUnbind()、onDestroy()方法會依次被調用
*
*/
public class Service02 extends Service {
// 第一步,定義一個Binder類型的子類,在子類種定義一個getService方法
public class MyBinder extends Binder {
public Service02 getService() {
return Service02.this;
}
}
//第二步,定義一個MyBinder類型的實例
private MyBinder mBinder = new MyBinder();
@Override
public void onStart(Intent intent, int startId) {
System.out.println("Service02 onStart.....");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("Service02 onStartCommand.....");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
System.out.println("Service02 onCreate.....");
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
System.out.println("Service02 onBind.....");
//第三步,在onBind方法中,返回MyBinder的實例
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("Service02 onUnBind.....");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
System.out.println("Service02 onDestroy.....");
super.onDestroy();
}
//第四步,在Service02中定義一個業務方法,讓外面與當前Service02綁定的組件能夠調用此方法,來完成既定目標
public int getRandomNumber(){
return new Random().nextInt(100);
}
}
最後把整個Demo的Android工程壓縮文件鏈接如下:
Android Service Demo
工作中遇到的Android內存優化問題(1)
最近工作中,遇到了幾個內存優化的問題,1.應用退出後,此應用進程保持了不少內存得不到釋放,用工具強制gc也無法釋放。2.應用進入某些頁面瞬間請求分配內存過大。此兩個問題對
Android項目研發之多分辨率適配
Android多終端適配是我們在實際開發中必然會遇到也必然要解決的問題,解決多終端適配的方法有很多,比如使用百分比布局庫(percent-support-lib)、在re
Android Developer:內存分析器
Heap Viewer,Memory Monitor和Allocation Tracker是用來可視化你的app使用內存的補充工具。使用Memory Monitor To
Android Studio快捷鍵指南(本文持續更新)
這是我在使用Android Studio過程中接觸到的一些快捷鍵,和大家分享,後面會繼續完善此文,也歡迎大家踴躍補充,一起完善。快捷鍵刪除並剪貼行:Ctrl+X復制一行: