Android在运行过程中所有程序都是主线程中执行的,因此当使用thread代码块实现一些组件的更新时,需要用到异步通信Handler。
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.service_test_main)//实现异步通信的方式进行更新数据val handler=object : Handler(Looper.getMainLooper()){override fun handleMessage(msg: Message) {when(msg.what){1->textView.text="师者所以传道授业解惑也"}}}//如果想在子线程里面进行组件的更新,需要使用到异步机制change_textView.setOnClickListener(){thread {val msg=Message()//更新文字msg.what=1handler.sendMessage(msg)}}}
使用步骤:1创建handler对象,在里面重写handlerMessage方法用来处理消息到达之后的逻辑。2建立消息Message对象,并且绑定发送消息的类别,让其能够区别不同逻辑的处理方式。3handler来发送消息
1在MyService中继承Service,实现其中的方法即可获得自定义的Service,主要有如onBinder的以下几个方法
//此方法用来和Activity进行通信使用override fun onBind(intent: Intent): IBinder {return mBinder}//只有第一次调用的时候才会执行override fun onCreate() {super.onCreate()}//每次启动时都会调用override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {return super.onStartCommand(intent, flags, startId)}override fun onDestroy() {super.onDestroy()}
在Activity中启动时和Activity的启动方式类似
start_service.setOnClickListener(){val intent= Intent(this,MyService::class.java)startService(intent)}end_service.setOnClickListener(){val intent=Intent(this,MyService::class.java)stopService(intent)}
1在service中继承Binder()类,在此类中进行逻辑的编写,将结果通过onBind()方法返回
class MyService : Service() {//为了实现和Activity的通信,模拟开启服务来进行下载功能private val mBinder=DownloadBinder()class DownloadBinder: Binder(){fun startDownload(){Log.d("MyService","开始下载")}fun getProgress():Int{Log.d("MyService","当前下载的进度")return 20}}//此方法用来和Activity进行通信使用override fun onBind(intent: Intent): IBinder {return mBinder}//只有第一次调用的时候才会执行override fun onCreate() {super.onCreate()}//每次启动时都会调用override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {return super.onStartCommand(intent, flags, startId)}override fun onDestroy() {super.onDestroy()}}
2在Activity中需要先对Activity和Service进行绑定,先实现ServiceConnection接口中的方法然后在方法里进行绑定之后的逻辑操作和解绑之后的逻辑操作。
class ServiceTest:AppCompatActivity() {lateinit var downBinder:MyService.DownloadBinderprivate val connnection=object :ServiceConnection{//该方法会在Activity与Service绑定之后进行调用override fun onServiceConnected(name: ComponentName?, service: IBinder?) {downBinder=service as MyService.DownloadBinderdownBinder.startDownload()downBinder.getProgress()}override fun onServiceDisconnected(name: ComponentName?) {Log.d("serviceTest","Service和Activity解绑成功")}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.service_test_main)//实现异步通信的方式进行更新数据val handler=object : Handler(Looper.getMainLooper()){override fun handleMessage(msg: Message) {when(msg.what){1->textView.text="师者所以传道授业解惑也"}}}//如果想在子线程里面进行组件的更新,需要使用到异步机制change_textView.setOnClickListener(){thread {val msg=Message()//更新文字msg.what=1handler.sendMessage(msg)}}//service的启动和停止start_service.setOnClickListener(){val intent= Intent(this,MyService::class.java)startService(intent)}end_service.setOnClickListener(){val intent=Intent(this,MyService::class.java)stopService(intent)}//数据和Service进行通信,获取到service的正在做的事情,需要对Service进行绑定bind_service.setOnClickListener(){val intent=Intent(this,MyService::class.java)bindService(intent,connnection, Context.BIND_AUTO_CREATE)//绑定service}unBind_service.setOnClickListener(){unbindService(connnection)}}
在主Activity中点击按钮就启动当前的Service在前台通知上
class ForegroundServiceTest : Service() {@RequiresApi(Build.VERSION_CODES.O)override fun onCreate() {super.onCreate()val manager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagerval channel=NotificationChannel("myService","前台Service通知",NotificationManager.IMPORTANCE_DEFAULT)manager.createNotificationChannel(channel)val intent=Intent(this,ServiceTest::class.java)val pi=PendingIntent.getActivity(this,0,intent,0)val notification=NotificationCompat.Builder(this,"myService").setContentTitle("前台Service主题").setContentText("前台的Service的内容").setSmallIcon(R.drawable.ic_baseline_arrow_back_ios_24).setLargeIcon(BitmapFactory.decodeResource(resources,R.drawable.ic_baseline_menu_24)).setContentIntent(pi).build()startForeground(1,notification)}override fun onBind(intent: Intent): IBinder {TODO("Return the communication channel to the service.")}
}
一般在Service中可能需要进行比较耗时的操作,而主线程又需要获得结果,但是当长时间没有获得结果之后就会出现ANR(Application Not Responding)的情况,因此为了解决这种情况更标准的写法是在Service中创建新的线程来处理任务进行异步的工作。
//每次启动时都会调用override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {thread{
//在里面进行逻辑的处理工作,最后别忘了进行关闭stopSelf()
}return super.onStartCommand(intent, flags, startId)}override fun onDestroy() {super.onDestroy()}
上一篇:python绘制三维图