位置: 编程技术 - 正文

Android之——任意时刻从子线程切换到主线程的实现(插曲)(android+)

编辑:rootadmin
一、引入

推荐整理分享Android之——任意时刻从子线程切换到主线程的实现(插曲)(android+),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:android之家,android xui,android的r,android xui,android+,android的r,android任务,android任务,内容如对您有帮助,希望把文章链接给更多的朋友!

在Android开发中常常会遇到网络请求,数据库数据准备等一些耗时的操作;而这些操作是不允许在主线程中进行的。因为这样会堵塞主线程导致程序出现未响应情况。

所以只能另起一个子线程进行这些耗时的操作,完成后再显示到界面。众所周知,界面等控件操作只能在主线程中完成;所以不可避免的需要从子线程切换到主线程。

二、方法

对于这样的情况在Android 中比较常见的是使用AsynTask类或者 Handler来进行线程切换;而其中AsynTask是官方封装的类,较为简单,效率也比较可以,但是并不适合所有的情况,至少我使用了一两次后就再也没有使用了。使用 Handler可以说是最万能的方式,其原理是消息循环,在主线程中建立Handler 变量时,就会启动Handler消息循环,一个个的处理消息队列中的任务。但是其也有棘手的时候;其棘手的地方就是麻烦。

每次都需要去建立一个 Handler 类,然后使用voidhandleMessage(Messagemsg) 方法把消息取出来进行界面操作,而其中还要遇到参数的传递等问题,说起来真的是挺麻烦的。

三、想法

既然有着这么多的问题,但是又有其的优势,我们何不自行封装一次呢?

这里我梳理一下思路:

还是使用 Handler进行线程切换在子线程中能通过简单的调用就切换到主线程进行工作在子线程切换到主线程时,子线程进入阻塞直到主线程执行完成(知道为什么有这样的需求么?)一定要保证其效率主线程的执行要有时间限制,不能执行太长时间导致主线程阻塞

我能想到的就是这些;观众老爷们咋样?可否还有需求?

说干就干,梳理一下实现方法

使用Handler 实现,既然这样那么主方法当然就是采用继承Handler 来实现而要简单同时又要能随时进入方法 那么对外采用静态方法是个不错的选择而要保证效率的话,那就不能让Handler 的消息队列过于太多,但是又要满足能随时调用,那么采用外部 Queue更具情况有阻塞与不阻塞子线程两种情况,那么采用两个 Queue吧,分开来好一点要保证不能长时间在主线程执行那么对于队列的执行一定要有时间限制加一个时间变量吧当然最后考虑了一下,既然要简单那么传入参数采用Runnable 是很爽的 四、代码

两个对外的方法简单来说就是这样了;但是其功能实现就需要使用继承Handler了。

建立类HandlerPoster,继承自Handler:

下面来说说这个我花了很大时间弄出来的类。类的变量部分:

两个标识,两个队列,两个执行状态,一个时间限制;很好理解吧?标识为了区别分别是处理那个队列使用;队列当然是装着任务了;执行状态是为了避免重复发送消息导致消息队列过多;时间限制这个最好理解了。

下面来说说方法部分

构造函数HandlerPoster(Looper_looper,int_maxMillisInsideHandleMessage):

传入两个参数,分别是 Looper,用于初始化到主线程,后面的是时间限制;然后初始化了两个队列。

销毁函数void_dispose():首先去除掉没有处理的消息,然后清空队列。

添加异步执行方法void_async(Runnable_runnable):

可以看见进入方法后第一件事儿就是进入同步状态,然后调用asyncPool.offer(runnable);把任务写入到队列。之后判断当前是否处于异步任务执行中,如果不是:立刻改变状态,然后发送一个消息给当前Handler,当然不要忘记了传入标识。当然为了效率其消息的构造也是通过obtainMessage(ASYNC)方法来完成,为的就是不过多建立新的Message,尽量使用当前队列中空闲的消息。

添加同步执行方法void_sync(SyncPost_post):

可以看到,这里传入的并不是Runnable 而是SyncPost这是为了同步而对Runnable进行了一次封装后的类;后面介绍。同样是进入同步,添加,判断,发送消息。

任务执行者@Override_void_handleMessage(Message_msg):

这里是复写的Handler的消息处理方法,当当前Handler消息队列中有消息的时候将会按照顺序一个个的调用该方法。

分段来看:

Android之——任意时刻从子线程切换到主线程的实现(插曲)(android+)

进入后首先判断是否是进行异步处理的消息,如果是那么进入该位置。进入后我们进行了try_finally有一个变量long_started用于标识开始时间。当执行一个任务后就判断一次如果超过了每次占用主线程的时间限制,那么不管队列中的任务是否执行完退出,同时发起一个新的消息到Handler循环队列。在while部分,我们从队列取出一个任务,采用Poll方法;判断是否为空,如果为空进入队列同步块;然后再取一次,再次判断。如果恰巧在进入同步队列之前有新的任务来了,那么第二次取到的当然就不是 NULL也就会继续执行下去。反之,如果还是为空;那么重置当前队列的状态为false同时跳出循环。

下面来看第二部分:

首先还是判断,如果是同步任务消息就进入,如果还是不是 那么只有调用super.handleMessage(msg);了。从上面的处理部分可以看出来其处理的过程与第一部分可以说是完全一样的。只不过是从不同队列取出不同的类SyncPost,然后判断执行,以及发送不同标识的消息;可以说如果懂了第一部分,这部分是毫无营养的。

这里就有问题了,既然方法操作流程一样,那么同步与异步是在哪里进行区分的?

这里就要看看SyncPost了:

首先看看SyncPost的构造函数:

是不是传入一个Runnable接口?所以说是对Runnable 的简单封装。

可以看见其public_void_run()方法:

在该方法中我们进入了同步块,然后调用Runnable接口的run方法。同时在执行完成后将其中的一个状态变量进行了改变boolean_end=true;然后调用this.notifyAll();通知等待的部分可以继续了,当然有这样的情况;假如在进入该同步块的时候子线程还未执行到this.wait();部分呢?所以我们为此准备了end和try。

然后看看public_void_waitRun()方法:

在这个中,我们首先判断状态,如果状态已经变了,那么证明子线程执行到此处时,主线程以及执行了void_run()。所以也就不用进入同步块进行等待了,不然那还不等死啊?反之就进入进行等待直到主线程调用this.notifyAll();

五、激情部分

回到类ToolKit

其中就一个静态变量HandlerPoster

然后一个初始化部分HandlerPoster_getMainPoster()这里采用同步的方式进行初始化,用于适应多线程同时调用情况;当然在初始化的时候我们传入了

mainPoster=newHandlerPoster(Looper.getMainLooper(),); 这里就决定了是在主线程执行的HandlerPoster,同时指定主线程单次运行时间为毫秒。

在方法void_runOnMainThreadAsync(Runnable_runnable)中:

首先判断调用该方法的是否是主线程,如果是那还弄到队列中执行干嘛?直接执行啊;如果是子线程就调用getMainPoster().async(runnable);追加到队列中执行。

而在方法void_runOnMainThreadSync(Runnable_runnable)中:

同样是线程判断,然后进行封装,然后丢进队列中等待执行,而在该方法中调用poster.waitRun();进行等待;直到主线程执行了SyncPost类的run方法。最后当然留下了一个销毁方法;妈妈说要学会清理不留垃圾:void_dispose()

OK,完成了。

对外就是这么两个方法,简单便捷啊;

代码类:

ToolKit.javaHandlerPoster.javaSyncPost.java

开源项目:Genius-Android

如何在Android studio中同时打开多个工程? 最近学习AndroidStudio,想同时打开两个Project。但是点击File-Open之后,原有的Project被关闭掉了。怎么在新的窗口中打开Project呢?解决:点击Help-FindAction,

在偏好文件中存储数据 SharedPreferences对象使用常规的XML文件来存储数据,这些文件存储在应用程序的数据目录内。该XML文件的结构很简单,因为它只允许存储键/对,不过AndroidA

【Android开发】 如何隐藏ListView的滚动条? setScrollbarFadingEnabled(true);Definewhetherscrollbarswillfadewhentheviewisnotscrolling.不活动的时候隐藏,活动的时候显示;setVerticalScrollBarEnabled(true);不活动的时候隐藏

标签: android+

本文链接地址:https://www.jiuchutong.com/biancheng/384314.html 转载请保留说明!

上一篇:Android 5.1 API 22 所有sdk文件下载地址

下一篇:如何在Android studio中同时打开多个工程?(如何在android studio中导入其他包)

  • 结转应交增值税是什么意思
  • 耕地占用税是什么税种
  • 利润分配未分配利润和未分配利润的区别
  • 劳务工报价单
  • 财产租赁合同金额含税吗
  • 个税代扣代缴手续费返还 申请
  • 无租房合同可以取住房公积金吗
  • 进口消费税为什么一定要组价
  • 汽车购买者
  • 普通发票没有明细可以吗
  • 给员工购买意外险进项税能不能抵扣
  • 境外机构可以开通b股账户
  • 红冲去年的收入怎么做账
  • 长期挂账其他应付款违反了哪项制度
  • 跨年暂估收入如何调整
  • 将汽车奖励给员工财务如何处理?
  • 税务社保扣取300干嘛的
  • 母子公司间的借款现金流计入哪里
  • 关税不可以抵扣吗
  • 0申报逾期罚款
  • 损益类科目包括收入类和费用类么
  • 个体工商户是否属于法人
  • 辅助生产费用的归集
  • 户外广告经营总额
  • 法定代表人的个人债务会执行公司财产么
  • 股东分红是看未交税吗
  • 技术开发合同收入包括哪些
  • 鸿蒙系统怎么设置导航键
  • 收到客户预付的货款的会计分录
  • owmngr.exe - owmngr是什么进程 作用是什么
  • 资产处置损益和待处理财产损溢区别
  • 员工内部罚款有没有上限和下限
  • 无形资产的转让
  • 股权换股权会计分录
  • 本期发出存货成本是什么意思
  • 事业单位增值税可以抵扣吗
  • 转让费交什么税
  • 机器学习论文源代码浅读:Autoformer
  • 毕业设计基于web难还是JAVA
  • 令人感到惊艳
  • 手工明细账簿怎么登账
  • 管家婆中已经过账的进货单怎么删除?
  • 招待客户发生的住宿费可以抵扣吗
  • 企业可以一次性现金的方式发放工资
  • 固定资产原值增加折旧怎么算
  • 固定资产的定义是什么?
  • 简易计税方法的适用范围
  • 一般纳税企业抵扣多少
  • 生产成本如何做核算
  • 优秀员工奖金领取表模板
  • 赔付支出包括
  • 运输公司的固定资产清单
  • 科目汇总表一张几行啊
  • 建筑企业人工费计入什么科目
  • sql中isnull是什么意思
  • upromise0.exe - upromise0进程是什么文件
  • ubuntu15.04系统怎么使用卸载命令卸载软件?
  • mac电脑自带软件介绍
  • 趣谈linux系统
  • 忘记mysql root密码的解决方法
  • mac隐藏菜单栏
  • linux限速
  • 双液浆常用配合比
  • win个性化设置没反应
  • win7系统连不了蓝牙
  • 笔记本怎么设置定时关机
  • android环境搭建实训心得
  • ExtJS4 Grid改变单元格背景颜色及Column render学习
  • python怎么用
  • unity shader视频教程
  • javascript的弹窗
  • 安卓开发界面ui设计器
  • 辽宁省社保系统操作
  • 税务催告期限多久
  • 国税发票打印汇总怎么弄
  • 电子税务局季度利润表本月数
  • 全国税务系统全面从严治党工作会议2023年
  • 购买的土地没有土地使用证
  • 中国的消费税是怎么算的
  • 累计预扣预缴税额
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设