菜鸟笔记,高手绕过。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