关于Service,你要知道的一些知识
来源:互联网 发布:飞书互动 知乎 编辑:程序博客网 时间:2024/06/06 09:57
Service到底是什么? 服务,它是在后台运行一些耗时的任务同时不与用户交互或用于其他应用程序使用,比如下载,更新天气等等。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。
Service的基本用法
首先创建服务:MyService.java
并重写父类的onCreate()、onStartCommand()和onDestroy()方法
public class MyService extends Service { public static final String TAG = "MyService"; public MyService() { } @Override public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: executed" ); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand() executed"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "onDestroy: executed"); } @Override public IBinder onBind(Intent intent) { return null; }}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.eason.servicetest.MainActivity"> <Button android:id="@+id/start_service" android:layout_width="379dp" android:layout_height="60dp" android:text="start service" tools:layout_editor_absoluteY="0dp" android:layout_marginRight="8dp" app:layout_constraintRight_toRightOf="parent" android:layout_marginLeft="8dp" app:layout_constraintLeft_toLeftOf="parent" tools:layout_editor_absoluteX="-143dp"/> <Button android:id="@+id/stop_service" android:layout_width="400dp" android:layout_height="53dp" android:text="Stop Service" android:layout_marginTop="45dp" app:layout_constraintTop_toBottomOf="@+id/start_service" android:layout_marginLeft="8dp" app:layout_constraintLeft_toLeftOf="parent" android:layout_marginRight="8dp" app:layout_constraintRight_toRightOf="parent" tools:layout_editor_absoluteX="-164dp"/></android.support.constraint.ConstraintLayout>
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button startService; private Button stopService; @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); startService.setOnClickListener(this); stopService.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; default: break; } }}
运行程序:
点击第一个按钮:
再次点击第一个按钮:
发现 onCreate()方法没有执行,因为在第一次点击的时候,service就已经被创建了,所以无论你点击多少次,都只有onStartCommand()方法在执行。
点击第二个按钮:
服务被销毁。
Service和Activity通信
如何使Service和Activity通信呢? 仔细点你会发现在MyService里有个onBind()方法,比如现在实现下载(非真实,下篇会写)的功能,
接下修改 MyService.java:
public class MyService extends Service { public static final String TAG = "MyService"; private DownloadBinder down = new DownloadBinder(); public MyService() { } @Override public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: executed" ); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand() executed"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "onDestroy: executed"); } @Override public IBinder onBind(Intent intent) { return down; } class DownloadBinder extends Binder{ public void startDownload(){ Log.e(TAG, "startDownload" ); } public int getProgress(){ Log.e(TAG, "getProgress"); return 0; } }}
添加两个按钮,一个绑定活动,另一个解除绑定。
在 activity_main.xml 添加这两个按钮:
<Button android:id="@+id/bind_service" android:layout_width="439dp" android:layout_height="55dp" android:text="Bind Service" android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="@+id/stop_service" android:layout_marginBottom="8dp" app:layout_constraintBottom_toTopOf="@+id/unbind_service" app:layout_constraintVertical_bias="0.395" android:layout_marginLeft="8dp" app:layout_constraintLeft_toLeftOf="parent" android:layout_marginRight="8dp" app:layout_constraintRight_toRightOf="parent"/> <Button android:id="@+id/unbind_service" android:layout_width="387dp" android:layout_height="57dp" android:text="Unbind Service" android:layout_marginRight="8dp" app:layout_constraintRight_toRightOf="parent" android:layout_marginLeft="8dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintHorizontal_bias="0.473" app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="208dp"/>
修改MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button startService; private Button stopService; private Button bindService; private Button unbindService; private MyService.DownloadBinder mDownloadBinder; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mDownloadBinder = (MyService.DownloadBinder)service; mDownloadBinder.startDownload(); mDownloadBinder.getProgress(); } @Override public void onServiceDisconnected(ComponentName name) { } }; @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,mConnection,BIND_AUTO_CREATE);//绑定服务 break; case R.id.unbind_service: unbindService(mConnection);//解除绑定 break; default: break; } }}
这里我们创建了ServiceConnection的匿名类,在里面重写了onServiceConnected()和onServiceDisconnected()的方法,这两个方法分别在 连接和断开时候启用。
bindService()方法,第一个参数接受Intent的对象,第二个参数就是前面创建的ServiceConnection的实例。
第三个参数则是一个标志位,这里的BIND_AUTO_CREATE表示在活动和服务进行绑定后自动创建服务,这会使MyService内的onCreate()方法得到执行,而onStartCommand()不会。
效果图:
点击 bindService:
注意:
任何一个服务都是通用的,可以和任何活动进行绑定而且绑定后都可以获取到相同的实例。
进阶Service
创建前台Service:
修改MyService.java:
@Override public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: executed" ); Intent intent = new Intent(this,MainActivity.class); PendingIntent pi = PendingIntent.getActivity(this,0,intent,0); Notification notification = new NotificationCompat.Builder(this) .setContentTitle("标题") .setContentText("内容") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.ic_launcher_round) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)) .setContentIntent(pi) .build(); startForeground(1,notification); }
其他和使用通知的流程一样。但是这里要注意的是 startForeground的方法会让MyService变成一个前台服务,并且在系统通知栏显示出来。
效果图:
IntentService
前面提到服务用来做耗时的事情,如果在主线程内这么默认使用,很容易出现 ANR 即应用无响应。
所以这时候就要用到多线程的知识。
在MyService:
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand() executed"); new Thread(new Runnable() { @Override public void run() { //处理具体的逻辑 stopSelf();//停止服务,自动停止功能。 } }); return super.onStartCommand(intent, flags, startId); }
另一种用法:
创建IntentService:
public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; public MyIntentService(){ super("MyIntentService"); } @Override protected void onHandleIntent(@Nullable Intent intent) { //打印当前线程id Log.e(TAG, "onHandleIntent: id is "+Thread.currentThread().getId()); } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "onDestroy"); }}
修改MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { .................... private Button intentService; private MyService.DownloadBinder mDownloadBinder; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mDownloadBinder = (MyService.DownloadBinder)service; mDownloadBinder.startDownload(); mDownloadBinder.getProgress(); } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { ................ intentService = (Button)findViewById(R.id.start_intent_service); ............... intentService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { .......... case R.id.start_intent_service: Log.e("MainActivity", "onHandleIntent: id is "+Thread.currentThread().getId()); Intent intentServices = new Intent(this,MyIntentService.class); startService(intentServices); break; default: break; } }}
在AndroidManifest.xml 添加一个按钮:
<Button android:id="@+id/start_intent_service" android:layout_width="380dp" android:layout_height="49dp" android:text="start intentService" tools:layout_editor_absoluteX="2dp" android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="@+id/unbind_service" app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="8dp" app:layout_constraintVertical_bias="0.293"/>
在onHandleIntent()方法内是用来处理一些具体的逻辑的;
下面的效果图可以看出,服务是在子线程内启动的,并且会自动关闭。
效果图:
服务的生命周期
服务也有自己的生命周期,一旦在项目的任何位置调用了Context的startService()方法,相应的服务就会启动起来,并且会调用onStartCommand()的方法。如果这个服务没有被创建,则onCreate()方法则会优先于onStartCommand()方法。服务启动后,会一直保持运行状态,直到stopService()或stopSelf()方法被调用。注意虽然每调用一次satrtService()方法,onStartCommand()方法会被调用一次,但是实际上只有一个该服务的实例。
同样,bindService()方法会调用onBind()方法,类似的模式和上面相同。
注意一点,我们有时候一个服务既使用startService()和bindService()方法,这种情况下销毁服务,要同时调用stopService()和unbindServcie()方法才会执行onDestroy()方法。
- 关于Service,你要知道的一些知识
- 你所不知道的Service知识
- 关于 service 你需要知道的
- 我想知道一些关于vxworks的知识
- Android Service中一些你不知道的细节
- JAVA-最最最最基础的一些知识,你知道吗?
- 关于Android屏幕适配应该知道的一些知识
- 关于Android屏幕适配应该知道的一些知识
- 关于移动网站开发你需要知道的知识【译】
- 关于压力:你得知道的20个小知识
- 说说关于Servlet你不知道的知识
- 关于蓝牙开发,你必须知道的知识
- Android中关于AudioFocus你所该知道的知识
- 关于so文件你需要知道的知识
- 关于Audio你应该知道的一点知识
- 关于Oracle安装程序和补丁要知道的一些知识[收集中]
- 你必须知道的关于javascript的一些问题
- 关于HTML你可能不知道的一些知识点
- 125.关于iPhone像素和各机型显示的探究
- jvm gc日志分析
- 完美解决主工程与lib库的provider冲突
- java的反射机制原理
- 原创短视频的美好时代,美拍连出两招加速达人变现
- 关于Service,你要知道的一些知识
- JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
- unity运行之自动暂停——作死
- 高斯低通高通函数
- ScrollView嵌套recyclerView问题
- luogu2461递归数列
- Http 学习
- 1019. 数字黑洞 (20)
- Android线程—Timer类(一)