Activity与Service进行通讯: android
public class MyService extends Service { public static final String TAG = "MyService"; private MyBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate() executed"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { // 开始执行后台任务 Log.d(TAG, "onStartCommand() executed"); } }).start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy() executed"); } @Override public IBinder onBind(Intent intent) { return mBinder; } class MyBinder extends Binder { public void startDownload() { new Thread(new Runnable() { @Override public void run() { // 执行具体的下载任务 Log.d(TAG, "startDownload() executed"); } }).start(); } } }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/start_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start Service" /> <Button android:id="@+id/stop_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Stop Service" /> <Button android:id="@+id/bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Bind Service" /> <Button android:id="@+id/unbind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Unbind Service" /> </LinearLayout>
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button startService; private Button stopService; private Button bindService; private Button unbindService; private MyService.MyBinder myBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { //向下转型 myBinder = (MyService.MyBinder) service; myBinder.startDownload(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startService = (Button) findViewById(R.id.start_service); stopService = (Button) findViewById(R.id.stop_service); bindService = (Button) findViewById(R.id.bind_service); unbindService = (Button) findViewById(R.id.unbind_service); startService.setOnClickListener(this); stopService.setOnClickListener(this); bindService.setOnClickListener(this); unbindService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start_service: Intent startIntent = new Intent(this, MyService.class); startService(startIntent); break; case R.id.stop_service: Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent); break; case R.id.bind_service: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); break; case R.id.unbind_service: unbindService(connection); break; default: break; } } }
只有在service与activity没有关联,也没有启动时,才会去执行Destroy()方法服务器
简单来讲进行通讯的俩种方式:app
1.BindService():异步
当Activity经过bindService来绑定一个Service时,bindService会当即返回,可是他不会返回Ibinder给客户端,要接收Ibinder,客户端Activity必须创建一个长链接ServiceConnection 的实例,并传给bindService(),ServiceConnection 包含一个回调方法来传递要返回的IBinderide
2.startService():oop
经过广播来实现通讯布局
Thread与Service的区别:ui
Thread是程序执行的最小单位,它是分配CPU的基本单位,能够用Thread来执行一些异步的操做,是由应用程序托管this
Service是系统的组件,它是由系统进程托管url
Thread的运行时独立于Activity的,因此所没有办法在不一样的Activity中对同一个Thread进行控制
Service是运行在进程中的主线程中的,而你能够在任何有Context的地方调用,开启服务,绑定服务,中止服务,以及接触绑定来控制它,也能够在Service里面注册广播,在其余地方发送广播来控制它,这些都是Thread作不到的
建立前台Service:
在Activity的OnCreate()方法中:首先建立一个Notification,而后进行初始化布局和控件,而后调用startForeground()方法
public class MyService extends Service { public static final String TAG = "MyService"; private MyBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); Intent notifyIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent,0); Notification notification = new Notification.Builder(this). setWhen(System.currentTimeMillis()). setAutoCancel(false). setSmallIcon(R.mipmap.ic_launcher). setContentTitle("通知"). setContentText("我是服务的通知"). setContentIntent(pendingIntent). setDefaults(Notification.DEFAULT_ALL). // 设置用手机默认的震动或声音来提示 build(); // 设置为前台服务,在系统状态栏显示 startForeground(1, notification); } }
Service的优先级:
经过startForeground(true)来设置Service的优先级,默认启动的Service是被标记为background,也就是说设置foreground,那么他就和正在运行的Activity优先级获得了必定得提升
如何保证Service不被杀死:
1.提高Service的优先级
2.在onDestory()中从新启动服务
3.监听系统广播判断Service状态
经过系统的一些广播,好比:手机重启、界面唤醒、应用状态改变等等监听并捕获到,而后判断咱们的Service是否还存活
4.双进程Service
让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程能够当即重启进程
5.用户不干预,彻底靠系统来控制,办法有不少。好比onStartCommand()方法的返回值设为START_STICKY
,服务就会在资源紧张的时候被杀掉,而后在资源足够的时候再恢复。固然也可设置为前台服务,使其有高的优先级,在资源紧张的时候也不会被杀掉
6.守护进程:
守护进程通常在系统启动时开始运行,除非强行终止,不然直到系统关机都保持运行
守护进程(Daemon Process),也就是一般说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程。它是一个生存期较长的进程,一般独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件。
守护进程是个特殊的孤儿进程,这种进程脱离终端,为何要脱离终端呢?之因此脱离于终端是为了不进程被任何终端所产生的信息所打断,其在执行过程当中的信息也不在任何终端上显示。因为在 Linux 中,每个系统与用户进行交流的界面称为终端,每个今后终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。
Linux 的大多数服务器就是用守护进程实现的。好比,Internet 服务器 inetd,Web 服务器 httpd 等
IntentService
IntentService是继承并处理异步请求的一个类,在IntentService内有一个工做线程来处理耗时操做,启动IntentService的方式和启动传统的Service同样,同时,当任务执行完后,IntentService会自动中止,而不须要咱们手动去控制或stopSelf()。另外,能够启动IntentService屡次,而每个耗时操做会以工做队列的方式在IntentService的onHandleIntent回调方法中执行,而且,每次只会执行一个工做线程,执行完第一个再执行第二个,以此类推。
package com.example.service; import android.app.IntentService; import android.content.Intent; import android.os.Looper; import android.support.annotation.Nullable; import android.util.Log; /** * Created by 郝悦 on 2018/1/30. */ public class MyIntentService extends IntentService { public static final String TAG ="MyIntentService"; /** * Creates an IntentService. Invoked by your subclass's constructor. * */ public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(@Nullable Intent intent) { // 这里已是工做线程,在这里执行操做就行 boolean isMainThread = Thread.currentThread() == Looper.getMainLooper().getThread(); Log.i(TAG,"is main thread:"+isMainThread); // 执行耗时下载操做 mockDownload(); } /** * 模拟执行下载 */ private void mockDownload(){ try { Thread.sleep(5000); Log.i(TAG,"下载完成..."); }catch (Exception e){ e.printStackTrace(); } } }
判断了是否为主线程,结果为false ,说明是开启了一个工做线程,5s 以后,打印了下载完成,而且自动中止了服务。
特色:
1.建立了一个独立的工做线程来处理全部的经过onStartCommand()传递给服务的intents
2.建立一个工做队列,来逐个发送intent给onHandlerIntent()
3.不须要主动调用stopSelft()来结束服务
4.默认实现的onBind()返回null
5.默认实现的onStartCommand()的目的是将intent插入到工做队列中,由于在全部的intent被处理完后,系统会自动关闭服务
IntentService
本质 = Handler
+ HandlerThread
:
HandlerThread
单独开启1个工做线程:IntentService
Handler
:ServiceHandler
ServiceHandler
与 IntentService
onStartCommand()
传递服务intent
到ServiceHandler
、依次插入Intent
到工做队列中 & 逐个发送给 onHandleIntent()
onHandleIntent()
依次处理全部Intent
对象所对应的任务