Android中HandlerThread和IntentService详解
2015-12-06 20:26
471 查看
在Android中有两种线程UI线程和子线程,我们都很清楚如果在UI线程进行耗时处理的话就容易引起ANR、如果是一个网络请求放在UI线程处理的话也会引起NetworkOnMainThreadExeception异常,对于这些情况我们就需要开启新的线程来处理。
HandlerThread使用
首先看名字我们就知道肯定Handler跑不了确实也是如此,在此我们需要一个Handler来处理异步需求,其中需求只是简单的一个网络请求。
定义完成Handler之后我们的HandlerThread就该初始化了
HandlerThread的工作原理其实很简单,首先一个HandlerThread是extends自Thread所以他是一个线程,那么我们Handler在这个线程中初始化就会运行在HanderThread这个线程中,Handler中的Looper就会轮询该线程对应的Message从而回调handlerMessage方法中去所以整个流程都是在子线程中运行从而起到跟Thread一样的异步效果。
这是一段HandlerThread的源码,所以Handler在初始化之前必须保证HandlerThread已经调用了start,因为如果没start那么Looper就没有执行prepared会引起异常。
最后,我们需要记得当不需要的时候记得调用HandlerThread.quit()方法移除可能未完成的操作避免内存泄露等危险养成一种良好的习惯。
IntentService的使用
IntentService的本质是一个Service内部使用HandlerThread来处理异步请求,每一次请求完成之后会自我的stopSelf来停止Service,所以很适合用于后台完成异步请求相比Service整体性能更优。
我们可以看到在onCreate中完成了HandlerThread初始化,这时候mServiceHandler就开始监听startService。
我们在UI线程通过跟启动Service一样通过intent启动一个IntentService会在onStart把intent转到sServiceHandler中去。
再看看下ServiceHandler的源码:
可以看到在handleMessage调用onHandleIntent这个抽象方法可见为什么我们新建一个IntentService需要重写onHandleIntent方法且在里面处理事务就好。
下面一段测试代码,通过intent把请求的地址传进来然后在IntentService执行一次请求:
在ServiceHandler中我们可以看见执行完onHandleIntent后会调用stopSelf(msg.arg1)来stop这个Service,当然如果这个时候还有其他的消息还未处理完成则会等待其他完成后再执行stopSelf。
HandlerThread使用
首先看名字我们就知道肯定Handler跑不了确实也是如此,在此我们需要一个Handler来处理异步需求,其中需求只是简单的一个网络请求。
class TestHandler extends Handler { public TestHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { try { URL url = new URL("http://www.baidu.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); InputStream is = connection.getInputStream(); String result = null; String input; BufferedReader reader = new BufferedReader(new InputStreamReader(is)); while ((input = reader.readLine()) != null) { result += input; } Log.w("TestHandler", result); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
定义完成Handler之后我们的HandlerThread就该初始化了
HandlerThread handlerThread = new HandlerThread("test_thread"); handlerThread.start(); TestHandler handler = new TestHandler(handlerThread.getLooper()); handler.sendEmptyMessage(0);
HandlerThread的工作原理其实很简单,首先一个HandlerThread是extends自Thread所以他是一个线程,那么我们Handler在这个线程中初始化就会运行在HanderThread这个线程中,Handler中的Looper就会轮询该线程对应的Message从而回调handlerMessage方法中去所以整个流程都是在子线程中运行从而起到跟Thread一样的异步效果。
public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; }
这是一段HandlerThread的源码,所以Handler在初始化之前必须保证HandlerThread已经调用了start,因为如果没start那么Looper就没有执行prepared会引起异常。
最后,我们需要记得当不需要的时候记得调用HandlerThread.quit()方法移除可能未完成的操作避免内存泄露等危险养成一种良好的习惯。
IntentService的使用
IntentService的本质是一个Service内部使用HandlerThread来处理异步请求,每一次请求完成之后会自我的stopSelf来停止Service,所以很适合用于后台完成异步请求相比Service整体性能更优。
public void onCreate() { // TODO: It would be nice to have an option to hold a partial wakelock // during processing, and to have a static startService(Context, Intent) // method that would launch the service & hand off a wakelock. super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
我们可以看到在onCreate中完成了HandlerThread初始化,这时候mServiceHandler就开始监听startService。
Intent intent = new Intent(); intent.setClass(MainActivity.this, TestIntentService.class); intent.putExtra("content", "http://www.baidu.com"); startService(intent);
我们在UI线程通过跟启动Service一样通过intent启动一个IntentService会在onStart把intent转到sServiceHandler中去。
public void onStart(Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
再看看下ServiceHandler的源码:
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); } }
可以看到在handleMessage调用onHandleIntent这个抽象方法可见为什么我们新建一个IntentService需要重写onHandleIntent方法且在里面处理事务就好。
下面一段测试代码,通过intent把请求的地址传进来然后在IntentService执行一次请求:
public class TestIntentService extends IntentService { /** * Creates an IntentService. Invoked by your subclass's constructor. */ public TestIntentService() { super("TestIntentService"); } @Override protected void onHandleIntent(Intent intent) { String urlName = intent.getStringExtra("content"); try { URL url = new URL(urlName); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); InputStream is = connection.getInputStream(); String result = null; String input; BufferedReader reader = new BufferedReader(new InputStreamReader(is)); while ((input = reader.readLine()) != null) { result += input; } Log.w("TestIntentService", result); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
在ServiceHandler中我们可以看见执行完onHandleIntent后会调用stopSelf(msg.arg1)来stop这个Service,当然如果这个时候还有其他的消息还未处理完成则会等待其他完成后再执行stopSelf。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories