在项目中遇到了登录取消的问题,由于登录用的是使用HandlerThrad新开一条线程的做法,网上的教程都是设置标志位或者使用HandlerThread的interrupt()方法。
个人认为使用handler新开一条线程更新UI的方法,只要handler使用.post()方法把线程放入了线程队列中,而且队列中无其他线程对象,该线程会立即执行,所以无法取消,只能通过handler的消息处理方法,将返回的Message不做处理而已。如果该线程对象在队列中未执行,可以使用Handler的removeCallbacks (Runnable r)方法将线程对象从队列中移除。
网上说得取消一个线程中在线程开始处加标志位做判断的方法:
在线程中做个标志boolean cancel = false;线程每一步操作之前都检测if(cancel),用户取消的时候cancel = true;
boolean cancel = false; //线程每一步操作之前都检测while(cancel),用户取消的时候 cancel = true; Runnable updateThread =new Runnable() { @Override public void run() { while(cancel){ handler.post(updateThread); //类似递归,也可使用handler.postDelayed(updateThread, 3000); } } } handler.post(updateThread);
这种仅适合于处理很耗时的操作,比如下载一个大文件,为了保持线程的运行 一般都是用循环来保持线程处于执行状态, 线程每一步操作之前都检测cancle这个标志位,这种方法的弊端就是不够实时,可能会有一定的延时。如果是采用新开一个线程处理发送一个请求并或得服务器响应的情况,使用标志位的做法就毫无意义,因为这种情况下线程不是出于循环状态。
正确的处理登录取消的关键代码如下:
private boolean iscancel = false; //用户手动取消登录的标志位 handlerThread = new HandlerThread("myHandlerThread"); handlerThread.start(); handler = new MyHandler(handlerThread.getLooper()); // 将要执行的线程对象添加到线程队列中 handler.post(new Runnable() { @Override public void run() { Message message = handler.obtainMessage(); UserBean user = Bbs.getInstance().Login(username, password);//耗时任务 Bundle b = new Bundle(); b.putSerializable("user", user); message.setData(b); message.sendToTarget(); //或使用 handler.sendMessage(message); } }); class MyHandler extends Handler { public MyHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { if(iscancel == false){ // 操作UI线程的代码 Bundle b = msg.getData(); UserBean user = (UserBean)b.get("user"); ...... } } }
当用户点击登录按钮登录的时候,弹出等待的ProgressDialog,这个ProgressDialog要添加取消的监听:
private ProgressDialog processDialog; processDialog.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { iscancel = true; } }
AsyncTask在这个问题上处理任务取消的方法和HandlerThread类似,只是线程取消是再handleMessage方法中处理,而AsyncTask对应HandlerMessage的方法是onPostExecute。AsyncTask比使用HandlerThread更加轻量,推荐使用。
相关推荐
三种不同的方式讲述了如何开辟新线程处理进度条的更新。运行时需修改Mainfest,来用不同的方式运行。默认是使用AsyncTask运行
AsyncTask是个好东西,能处理绝大多数应用线程和更新UI的任务,由于其内部使用了静态线程池,如果你有一堆异步任务(例如全局定时更新数据、同一个Activity中多个AsyncTask同时执行)其中有不能马上执行完的情况...
Android线程,线程池,AsyncTask,HandlerThread和IntentService的用法demo
测试Android主线程、子线程(thread、handlerThread、AsyncTask、timer)及线程间通信方式(handler、timetask、Runnable)的建立及工作过程
作为替代,Android有强大的基础类,像HandlerThread,AsyncTask,IntentService。Thread和Runnable也是ThreadPoolExecutor的基础类。这个类可以自动管理线程和任务队列,甚至可以并行执行多线程。 定义一个实现...
1、AsyncTask AsyncTask 是一种轻量级的异步任务类,可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新 UI, AsyncTask 是一个抽象的泛型类,提供了 Params(参数的类型)、...
对于移动开发者来说,“将耗时的任务放到子线程去执行,以保证UI线程的流畅性”是线程编程的第一金科玉律,但这条铁则往往也是UI线程不怎么流畅的主因。我们在督促自己更多的使用线程的同时,还需要时刻提醒自己怎么...
积分管理系统java源码 ...Android线程 为什么要同步 ...Android线程模型提供的Handler和HandlerThread 同步机制 Android线程模型就是消息循环,Looper关联MessageQueue,不断尝试从MessageQueue取出Message来
HandlerThread ThreadPoolExecutor 多进程 Socket 网络编程 WebView 数据存储技术 多媒体 音频 视频 摄像头 位置与传感器 位置服务 其它传感器 硬件连接 蓝牙 NFC USB Wi-Fi P2P SIP 优秀开源框架
文章共有10个段落,涉及的内容有:多线程并发的性能问题,介绍了AsyncTask、HandlerThread、IntentService与ThreadPool分别适合的使用场景以及各自的使用注意事项。这是一篇了解Android多线程编程不可多得的基础文章...
使用 Looper、处理程序和处理程序线程。 添加了内存 LruCache。 还在后续加载图像时重用位图,因为图像大小相同,这显着减少了 GC 启动。 使用这种方法比尝试使用 AsyncTask 要容易得多,而且绝对更具可读性。
AsyncTask/HandlerThread/IntentService UI View绘制原则 事件派发机制 /RecyclerView缓存机制 动画机制 开源库 网络:Okhttp/Retrofit/Vollery 图片加载:Fresco/Glide/Picasso/ImageLoader 事件总线:EventBus ...
11.2.3 HandlerThread 402 11.2.4 IntentService 403 11.3 Android中的线程池 406 11.3.1 ThreadPoolExecutor 407 11.3.2 线程池的分类 410 第12章 Bitmap的加载和Cache 413 12.1 Bitmap的高效加载 414 12.2 ...
11.2.3 HandlerThread / 402 11.2.4 IntentService / 403 11.3 Android中的线程池 / 406 11.3.1 ThreadPoolExecutor / 407 11.3.2 线程池的分类 / 410 第12章 Bitmap的加载和Cache / 413 12.1 Bitmap...