一.前言
我们都知道Service是运行在主线程中的一种后台机制,如果在service中执行耗时操作,就可能会导致ANR。那么在不使用IntentService的时候,我们在service中进行耗时操作都是怎么处理的呢,下面上伪代码
public class MyService extends Service {
....
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
//执行业务逻辑
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
可以发现的是,这种写法并不复杂,但是每次都要自己创建线程,还要在工作任务执行完之后即使调用stopSelf()停止服务。谷歌专门提供了一个IntentService类来简化程序员的工作
二.关于IntentService与源码分析
Google 为方便开发者使用,提高开发效率,封装了 IntentService 和 HandlerThread。HandlerThread 继承自 Thread,内部封装了 Looper。那 IntentService 呢? 首先我们来,阅读IntentService 的源码:public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@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 thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@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();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
public stract void onHandleIntent(@Nullable Intent intent);
}
我们先观察onCreate方法,开启一个HandlerThread线程,HandlerThread与普通Thread的区别在于,HandlerThread内部开启了自己的Looper 循环,可以通过获取其Looper往他的消息队列发消息。然后在实例化了一个ServiceHandler对象,构造方法传入了HandlerThread对象的Looper循环器。我们再来观察onStart 方法,通过obtainMessage方法构造消息并入队HandlerThread对象的消息队列,我们再来看ServiceHandler对消息的处理handleMessage方法,其实就是调用IntentService 子类的onHandleIntent方法。这样我们在子类onHandleIntent方法中实现耗时业务操作最终会在子线程中执行。
三.实现我们的IntentService
public class MyIntentService extends IntentService {
private boolean isRunning;
LocalBroadcastManager mLocalBroadcastManager ;
@Override
public void onCreate() {
super.onCreate();
//注册广播
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
}
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
try {
isRunning = true;
int progress = 0;
while (isRunning){
Thread.sleep(100);
progress++;
if(progress==100){
isRunning = false;
}
sendThreadStatus("Runing........",progress);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 发送进度消息
*/
private void sendThreadStatus(String status, int progress) {
Intent intent = new Intent(IntentServiceActivity.ACTION_TYPE_THREAD);
intent.putExtra("status", status);
intent.putExtra("progress", progress);
mLocalBroadcastManager.sendBroadcast(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
Activity的处理
public class IntentServiceActivity extends Activity {
ProgressBar progressbar;
TextView tv_progress;
public static String ACTION_TYPE_THREAD = "ACTION_TYPE_THREAD";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_service);
progressbar = findViewById(R.id.progressbar);
tv_progress = findViewById(R.id.tv_progress);
}
@Override
protected void onResume() {
super.onResume();
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_TYPE_THREAD);
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
manager.registerReceiver(receiver,filter);
Intent i = new Intent(IntentServiceActivity.this, MyIntentService.class);
startService(i);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(ACTION_TYPE_THREAD.equals(intent.getAction())){
//更改UI
int progress = intent.getIntExtra("progress", 0);
progressbar.setProgress(progress);
tv_progress.setText(progress + "%");
}
}
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_progress"
android:layout_width="40dp"
android:layout_height="20dp" />
<ProgressBar
android:max="100"
android:progress="50"
android:secondaryProgress="80"
android:id="@+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
在这里,我们模拟的时候一个后台更新的下载进度条,效果如下
后话
启动IntentService的方式,我们并不建议通过bindService() 启动 IntentService。原因很简单,查看源码,onBind方法默认返回null,,如果你执意要 bindService() 来启动 IntentService,那么 onHandleIntent() 不会被回调,相当于在你使用 Service@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
作者:王宗耀 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/wzy901213