四大组件之Service
AndroidAZ系列有以下目的:
- Android程序猿的面试(初级,中级,高级,资深),拿到满意的offer。
- Android程序猿学习进阶。
标记说明:因为笔者是列出所有的Android知识点,因此面试不需要看那么多内容,如果是面试的知识点。笔者会加上标记Face,而如果不是面试的知识点,笔者会加上No标记,它是要学的东西;然后笔者将Android面试者或者面试者分为4个等级,初级A1,中级A2,高级A3,资深A4,如果这个知识点是所有等级的范围,那么笔者将会以all标记上。因此进阶路线就是A1->A2->A3->A4。也是面试者挑选的复习范围,假如你是中级程序员,那么你面试要看的内容就是包含A2&Face的标记。
-
All : 所有的Android工程师都看。
-
A1: 初级Android工程师。
-
A2: 中级Android工程师。
-
A3: 高级Android工程师。
-
A4: 资深Android工程师。
-
Face: 是面试的知识点。
-
No: 面试基本遇不到。
1.Service 是什么
Android Service是Android四大组件之一,它主要用来执行一些不与用户交互的长期运行的任务. 服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另一个应用程序,服务仍然能够保持正常运行. 另外Service并不是运行在单独线程中,而是主线程中。所以尽量要避免耗时操作。
2.Service和线程的区别
2.1 线程的用法
-
方法一:
class MyThread extends Thread{ @Override public void run(){ // 耗时操作 } } new MyThread().start();
-
方法二:
class Mythread implements Runnable{ @Override public void run(){ // 耗时操作 } } Mythread mythread = new Mythread(); new Thead(mythread).start();
2.2 在子线程中更新UI
-
方法一:
public static final int MSG_ID = 100; private Handler handler = new Handler(){ public void handleMessage(Message msg){ switch(msg.what){ case MSG_ID: // 更新UI break; default: break; } } } new Thread(new Runnable(){ @Override public void run(){ Message message = new Message(); message.what = MSG_ID; handler.sendMessage(message); } }).start();
-
方法二:
这里的原理和方法一是一样的,只是进行了封装
@android.webkit.JavascriptInterface public void actionFromJs() { mMainView.getActivity().runOnUiThread(new Runnable() { @Override public void run() { MusicPlayerHelper.getIntence(mMainView.getContext().getApplicationContext()).stopBgSound(); Intent intent = new Intent(); intent.setClass(mMainView.getContext(), NocviceActivity.class);//打开一个activity mMainView.getActivity().startActivity(intent); } }); }
2.3 服务的用法
- 定义一个服务
public class MyService extends Service{
public MyService(){
}
@Override
public IBinder onBind(Intent intent){
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate(){
super.onCreate();
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
return super.onStartCommand(intent,flags,startId);
}
@Override
public void onDestroy(){
super.onDestroy();
}
}
- 在AndroidManifest.xml中进行注册
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:lable="@string/app_name"
android:suppertsRtl="true"
android:theme="@style/AppTheme">
...
<service
android:name=".MyService"
android:enable="true"
android:exported="true">
</service>
</application>
- 启动服务
Intent startIntent = new Intent(mContext,MyService.class);
mContext.startService(startIntent);
- 停止服务
Intent stopIntent = new Intent(mContext,MyService.class);
mContext.stopService(startIntent);
Service和Thread的区别
-
Service
-
在后台用来执行长时间运行操作的应用组件
-
Service的生命周期在主线程中执行,如果要执行耗时操作,需要开启一个分线程
-
应用退出,Service也不会停止
-
再次启动应用时,还可以和正在运行的Service通信
-
-
Thread
-
用来开启一个分线程的类,用来做耗时操作
-
Thread类的run()在分线程执行
-
应用退出,Thread也不会停止
-
再次启动应用,不能再控制之前的Thread对象
-
-
详细解释
其实这跟 android 的系统机制有关,我们先拿Thread 来说。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制
如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)
因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的
3.Service的生命周期
Service生命周期图3.1 startService
-
启动Service服务
单次:startService() —> onCreate() —> onStartCommand()
多次:startService() —> onCreate() —> onStartCommand() —> onStartCommand()
-
停止Service服务
stopService() —> onDestroy()
3.2 bindService
-
绑定Service服务
bindService() —> onCreate() —> onBind()
-
解绑Service服务
unbindService() —> onUnbind() —> onDestroy()
-
启动绑定Service服务
startService() —> onCreate() —> onStartCommand() —> bindService() —> onBind()
-
解绑停止Service服务
unbindService() —> onUnbind() —> stopService() —> onDestroy()
-
解绑绑定Service服务
unbindService() —> onUnbind(ture) —> bindService() —> onRebind()
3.3 onStartCommand()和onStart()区别
每调用一次startService()方法, onStartCommand()就会执行一次
onstart()方法是在android2.0一下的版本中使用。而在android2.0以上则使用onstartCommand()方法。它们两个方法放在一起使用时,不会产生冲突
4.Intent Service的使用
Intent Service时一个异步的 会自动停止的服务
public class MyIntentService extends IntentService{
public MyIntentService(){
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent){
// 耗时操作
Log.d("MyIntentService","This is is" + Thread.currentThread().getId());
}
@Override
public void onDestroy(){
super.onDestroy();
Log.d("MyIntentService","onDestroy executed");
}
}
这里首先要提供一个无参的构造函数,并且必须在其内部调用父类的构造函数.然后要在子类中去实现onHandleIntent()这个抽象方法,在这个方法里执行耗时逻辑,而不用担心ANR的问题,因为这个方法已经是在子线程中运行了.
5. Service使用场景
Service是一个应用程序中不可见的组件,用于处理运行时间长或者不需要用户交互的任务,比如一个股票应用,应用程序关掉了但是要给用户实时提供最新的数据,这时就可以使用Service
网友评论