菜鳥筆記,高手繞過。android
文章內容列表:git
1.分別經過startService和bindService的方式啓動服務,比較二者不一樣,及在此期間發現的問題。github
2.研究IntentService的 使用。app
public class MyActivity extends Activity {
private String TAG="TAG";less
Button startButton,stopButton,startIntentServiceButton,stopIntentServiceButton,jumpButton;
ServiceConnection mServiceConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
startButton= (Button) findViewById(R.id.button);
stopButton= (Button) findViewById(R.id.button2);
startIntentServiceButton= (Button) findViewById(R.id.intentService_button);
stopIntentServiceButton= (Button) findViewById(R.id.stop_intentService);
jumpButton= (Button) findViewById(R.id.jump_button);
jumpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Intent intent=new Intent(MyActivity.this,SecondActivity.class);
// startActivity(intent);
MyActivity.this.finish();
//android.os.Process.killProcess(android.os.Process.myPid());
}
});
startIntentServiceButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v(TAG,"startIntentServiceButton is pressed");
MyIntentService myIntentService=new MyIntentService("myIntentService");
Intent intent=new Intent(MyActivity.this,MyIntentService.class);
startService(intent);
// bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);
}
});
stopIntentServiceButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MyActivity.this,MyIntentService.class);
stopService(intent);
/**
* 當調用stopService方法時,service的onDestroy方法會當即被調用,可是服務裏面新開的線程還在跑,直到跑完。
*/
// unbindService(mServiceConnection);
}
});
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v(TAG, "BUTTON IS CLICKED");
// startService(intent);
/**
* IntentService的啓動方式跟service的啓動方式是同樣的,但他本身管理本身的service,此處調用了startService方式後,會調用onHandleIntent方法
* onHandleIntent-->onDestroy.
* 也就是說IntentService本身處理完onHandleIntent方法後,就會本身結束本身。大無畏的精神啊,而後就調用onDestroy了。
*/
Intent intent = new Intent(MyActivity.this, MyService.class);
IntentService intentService;
Handler handler;
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
// startService(intent);
/***
* 調用startService以後,service調用onCreate 和onStartCommand方法,經過該方法啓動的service會一直在運行,即便他的調用方已經結束了。
*因此若是使用這種方式啓動,If you implement this, it is your responsibility to stop the service
/***
* 調用bindService要傳進去一個ServiceConnection 參數,bindService方法調用後會調用onCreate ,onBind方法,和onServiceConnected方法
* 調用次序是onCreate--->onBind----->onServiceConnected
* 經過該Binder能夠實現Service和調用方的通訊。
*/
/***
* 不論是startService仍是bindService方式啓動的服務。從啓動服務的activity跳轉到另外一個activity,
* 該服務也還會繼續跑。
* 可是二者的不一樣是:
* 當啓動服務的activity destroy掉不會影響startService方式啓動的service即便沒有調用stopService,也不會有影響
* 但經過bindService啓動的服務若是此時沒有主動調用unBindService,而後就調用啓動他的activity的finish方法,此時,該activity的
* onDestroy方法不會被調用,多是由於資源沒有釋放的緣由吧。若是此時你將你的程序按多任務鍵將其從歷史任務中劃掉,此時會調用onDestroy方法
* 固然也會報內存泄露的錯誤,由於以前沒有調onDestroy方法就是由於資源沒有釋放,固然是猜想了。
* 但還有一種狀況,若是你經過android.os.Process.killProcess(android.os.Process.myPid());
* 將程序殺死的話就不會報內存泄露的錯誤,也許該方法自己會幫你作些處理吧,可是activity的onDestroy方法依然不會被調用。
* 也就是說bindService方式啓動的service是依附於啓動他的activity的。
*/
Context context;
}
});
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MyActivity.this,MyService.class);
unbindService(mServiceConnection);
// stopService(intent);
}
});
mServiceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyService.MyBinder myBinder= (MyService.MyBinder) service;
int count=myBinder.getCount();
Log.v(TAG,"COUNT IS "+count);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v(TAG,"!!1--onServiceDisconnected");
}
};
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.v(TAG,"---onDestroy");
}
}
ide
MyService類:函數
public class MyService extends Service {
private static String TAG="TAG";
MyBinder myBinder=new MyBinder();
int count=0;
public MyService() {
}
/***
*
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.v(TAG,"ONBIND");
return myBinder;
}
class MyBinder extends Binder{
public int getCount(){
return count;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG,"SERVICE ONSTARTCOMMAND");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG,"service onDestroy");
}
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG,"SERVICE ONCREATE");
}
}
oop
MyIntentService類:測試
public class MyIntentService extends IntentService {
private static String TAG="TAG";
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public MyIntentService(String name) {
super("MyIntentService");
}
public MyIntentService(){
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.v(TAG,"onHandleIntent");
/*long futrueTime=System.currentTimeMillis()+5000;
//執行5s鍾。
while (System.currentTimeMillis()<futrueTime) {
Log.v(TAG, "ONHANDLEINTENT");
synchronized (this) {
try {
Log.v(TAG,"WAIT");
wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}*/
for (int i=0;i<15;i++){
Log.v(TAG,"ONHandleThread "+i);
try {
Log.v(TAG,"CurrentThread id is "+Thread.currentThread().getName());
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG,"----onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG,"----onCreate");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.v(TAG,"----INTENTSERVICE ONSTART");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG,"===onDestroy");
}
ui
}
例子中有5個按鈕,startButton和stopButton測試startService和bindService,startIntentService和stopIntentService測試IntentService.jumpButton來結束啓動服務的activity.具體說明例子中有註釋。
1.1經過startService方法啓動的服務跟啓動方沒有關係,即便啓動方destroy了,服務依然跑。
1.2但經過bindService啓動的服務,必須在activity 調用destroy以前釋放資源,unBindService,否則會形成資源泄露。
1.3像上面例子中bindService以後,若是按中止按鈕去unBindService,直接按jumpButton去結束當前activity,你會發現當前activity的onDestroy方法並無被調到。此處注意下。
1.4此時從後臺任務裏將應用劃掉會報內存泄露的錯誤。若是用android.os.Process.killProcess(android.os.Process.myPid());去結束掉整個應用,你會發現不會報內存泄露的錯誤,即便沒有調用unBindService方法。
2.IntentService是Service的子類,也須要在manifest裏面進行註冊,其中要注意MyIntentService必需要有一個空的構造函數,如代碼中實現,不然註冊會編譯不過。
3.普通Service類是運行在主線程裏的,要進行耗時操做須要本身新開線程,但IntentService能夠進行耗時操做,直接在onHandleIntent方法裏進行耗時操做就好。耗時操做完成後自動調用onDestroy方法,這一點注意,若是在進行耗時操做時你顯式調用stopService的方式結束IntentService,這時IntentService的onDestroy方法會當即被調用,但耗時操做仍是會繼續執行,直到執行結束。這一點的原理能夠從IntentService的源碼中看出:
public abstract class IntentService extends Service {
}
從源碼中能夠看出,IntentService內部新開啓了一個IntentThread的線程來處理耗時操做。當咱們經過startService的方式啓動IntentService時,會調用其的onStart和onStartCommand方法,這兩個方法裏面會去將你啓動IntentService時所用的Intent傳給Message的obj參數,而後將其發送給其內部的handler,在handler的handleMessage方法裏面就去調用handleIntent方法了,這就是爲何咱們啓動服務後IntentService就會去調用onHandleIntent方法的緣由了。同時咱們發如今handleMessage方法裏面onHandleIntent方法結束完以後,intentService就會調用stopSelf方法結束本身。IntentService的源碼仍是很是簡單的,相信你們都能看懂,記錄僅爲後來複習所用。如有錯誤,歡迎拍磚。代碼下載地址:https://github.com/happycodinggirl/AndroidLearningProcess.git