編輯:關於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() { //新建一個數組適配器 ArrayAdapterarrayAdapter = 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
最近工作中,遇到了幾個內存優化的問題,1.應用退出後,此應用進程保持了不少內存得不到釋放,用工具強制gc也無法釋放。2.應用進入某些頁面瞬間請求分配內存過大。此兩個問題對
Android多終端適配是我們在實際開發中必然會遇到也必然要解決的問題,解決多終端適配的方法有很多,比如使用百分比布局庫(percent-support-lib)、在re
Heap Viewer,Memory Monitor和Allocation Tracker是用來可視化你的app使用內存的補充工具。使用Memory Monitor To
這是我在使用Android Studio過程中接觸到的一些快捷鍵,和大家分享,後面會繼續完善此文,也歡迎大家踴躍補充,一起完善。快捷鍵刪除並剪貼行:Ctrl+X復制一行: