枕上诗书闲处好,门前风景雨来佳。这篇文章主要讲述Android Intent Service相关的知识,希望能为你提供帮助。
android Intent Service
学习自
- Android 官方文档
- https://blog.csdn.net/iromkoear/article/details/63252665
【Android Intent Service】IntentService 是Service的子类,他被用来根据需求处理异步(IntentService中存在一个工作线程)请求(表现为Intent,从类的名字也可以看出来)。 而且这个Service非常省心,当工作完成后会自动停止,不需要我们手动停止。
使用IntentService
下面是一个简单的通过IntentService来更新进度条的示例,示例流程如下:
- Activity中祖册临时的广播接受者,来接收消息,然后更新UI
- 点击Button开启IntentService,然后开始增加进度
- 当增加了进度以后,通过发送广播,来通知UI改变
文章图片
IntentService
class TestIntentService(name: String?) : IntentService(name) {
/**
* 注意必须要有一个无参数的构造函数
* 当前环境使用的API是API26
* IntentService并没有无参数的构造函数
* 所以我们这里需要自己创建一个
* 否则会报错
*
* name 参数 代表的工作线程的命名
* */
constructor() : this("
TestIntentService"
) {}companion object {
val ACTION_UPDATE_PROGRESS = "
com.shycoder.cn.studyintentservice.UPDATE_PROGRESS"
}private var progress = 0private lateinit var mLocalBroadcastManager: LocalBroadcastManagerprivate var isRunning = trueoverride fun onCreate() {
super.onCreate()
this.mLocalBroadcastManager = LocalBroadcastManager.getInstance(this)
}override fun onHandleIntent(intent: Intent?) {Log.e("
TAG"
, "
onHandleIntent"
)if (intent == null || intent.action != ACTION_UPDATE_PROGRESS) {
return
}this.isRunning = true
this.progress = 0while (isRunning) {
SystemClock.sleep(500)
progress += 10
if (progress >
= 100) {
this.isRunning = false
}
this.sendBroadcast(if (isRunning) "
running"
else "
finish"
, progress)
}
}/**
* send broadcast to activity for notifying change of status and progress
* */
private fun sendBroadcast(status: String, progress: Int) {
val intent = Intent()
intent.action = MainActivity.ACTION_STATUS_CHANGED
intent.putExtra("
status"
, status)
intent.putExtra("
progress"
, progress)
this.mLocalBroadcastManager.sendBroadcast(intent)
}}
Activity的代码
class MainActivity : AppCompatActivity() {val mReceiver = TestBroadcastReceiver()
lateinit var mLocalBroadcastManager: LocalBroadcastManageroverride fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)//register broadcast
val intentFilter = IntentFilter(ACTION_STATUS_CHANGED)
this.mLocalBroadcastManager = LocalBroadcastManager.getInstance(this)
mLocalBroadcastManager.registerReceiver(mReceiver, intentFilter)
}/**
* start intent service
* */
fun startIntentService(view: View) {
val intent = Intent(this, TestIntentService::class.java)
intent.action = TestIntentService.ACTION_UPDATE_PROGRESS
this.startService(intent)
}override fun onDestroy() {
super.onDestroy()
this.unregisterReceiver(this.mReceiver)}inner class TestBroadcastReceiver : BroadcastReceiver() {override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null) {
return
}
val status = intent.getStringExtra("
status"
)
val progress = intent.getIntExtra("
progress"
, 0)
tvStatus.text = status
progress_barTest.progress = progress}
}companion object {
val ACTION_STATUS_CHANGED = "
cn.shycoder.studyintentservice.STATUS_CHANGED"
}
}
多次开启IntentService
当我们试着连续点击多次Button(比如说三次), 稍等片刻就会发现进度条满了以后,又重新开始了直到三次位置。打印出来的Log如下:
E/TAG: onHandleIntent
E/TAG: onHandleIntent
E/TAG: onHandleIntent
通过Log和UI的变化,我们可以发现,如果多次开启Service的话,那么
onHandleIntent
方法就会执行多次,这一点与 Service
大相庭径需要我们格外的关注,至于为什么是这种情况,在接下来的源码解析中会提到。不要使用Bind的方式开启服务
在我们使用
Service
的时候,为了能和Service进行交互,我们会通过Bind的方式开启服务获取与Service进行通信的Binder,但是Bind开启服务的方式并不适用于 IntentService
下面我们来验证一下。class TestIntentService(name: String?) : IntentService(name) {
/**
* 注意必须要有一个无参数的构造函数
* 当前环境使用的API是API26
* IntentService并没有无参数的构造函数
* 所以我们这里需要自己创建一个
* 否则会报错
*
* name 参数 代表的工作线程的命名
* */
constructor() : this("
TestIntentService"
) {}private val mBinder = MyBinder()override fun onBind(intent: Intent?): IBinder {
Log.e("
TAG"
, "
onBind"
)
return this.mBinder
}inner class MyBinder : Binder() {
}
//...
}
绑定服务
class MainActivity : AppCompatActivity() {
//....
lateinit var mLocalBroadcastManager: LocalBroadcastManagerlateinit var mService: TestIntentService.MyBinderprivate val mConn = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
mService = service as TestIntentService.MyBinder
}override fun onServiceDisconnected(name: ComponentName?) {
}}/**
* bind intent service
* */
fun bindService(view: View) {
val intent = Intent(this, TestIntentService::class.java)
intent.action = TestIntentService.ACTION_UPDATE_PROGRESS
this.bindService(intent, this.mConn, Context.BIND_AUTO_CREATE)
}
//...
}
当我们BindService后,查看Log
E/TAG: onBind
我们发现
onHandleIntent
方法的Log并没有打印出来,这时候 IntentService
就是一个普通的Service了,而不具备IntentService的特性。由此我们可以得出结论——不用使用Bind的方式开启IntentService。IntentService源码解析
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
//looper
private volatile ServiceHandler mServiceHandler;
//handler
private String mName;
//线程的名字
private boolean mRedelivery;
/**
这个Handler是子线程的Handler,并不是与UI通信的Handler
*/
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
/**
调用 onHandleIntent
*/
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
//当所有的消息都处理完了就结束服务
stopSelf(msg.arg1);
}
}public IntentService(String name) {
super();
mName = name;
}public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}@Override
public void onCreate() {super.onCreate();
//实例化HandlerThread
//HandlerThread继承自Thread
HandlerThread thread = new HandlerThread("
IntentService["
+ mName + "
]"
);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}/**
众所周知,如果多次开启Service的话,那么 onStart方法就会执行多次
IntentService在onStart找那个不断地向Handler发送消息
*/
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}@Override
public void onDestroy() {
mServiceLooper.quit();
}/**
onBind 方法被重写,返回null
*/
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
上面的代码很简单,仅仅是对Service进行了一层封装,大致流程如下:
- 当创建service的时候,进行IntentService的初始化操作(onCreate),实例化 HandlerThread
- onCreate方法执行以后,紧接着就会调用
onStart
方法,这时候就像向Handler发送消息 - handler 会进行排队执行
- 当所有的消息都处理完成了以后,会将服务结束
onStart
生命周期方法。 所以虽然 Bind的方式开启Service会执行onCreate方法来实例化 HandlerThread
但是因为 onStart
方法才向Handler 中发送数据。推荐阅读
- Android studio使用android:style/Theme.Dialog报错:You need to use a Theme.AppCompat theme (or descendant)
- android studio connot resolve
- SpringBoot解决测试环境,生产环境使用不同application.properties的问题
- android -------- Data Binding的使用 ( 六) 自定义属性
- Android dpdpipx
- java/android 做题中整理的碎片小贴士(12)
- VMWARE Thin APP
- 慕测Appium
- Android 各种路径详细说明