发明内容
为克服相关技术中存在的问题,本申请实施例提供一种避免应用触发ANR的方法及装置。
根据本申请实施例的第一方面,提供一种避免应用触发ANR的方法,包括:
确认第一进程的UI线程待执行的操作为耗时操作;
启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端;
所述第一进程的UI线程开始执行所述耗时操作;
当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
根据本申请实施例的第二方面,提供一种避免应用触发ANR的方法,包括:
确认第一进程的UI线程待执行的操作为耗时操作;
所述第一进程的UI线程开始执行所述耗时操作;
在触发应用程序无响应所述ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端;
当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
根据本申请实施例的第三方面,提供一种避免应用触发ANR的方法,包括:
第一进程的UI线程执行操作;
确认所述操作为耗时操作;
在触发应用程序无响应所述ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端;
当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
根据本申请实施例的第四方面,提供一种避免应用触发ANR的装置,包括:
确认单元,用于确认第一进程的UI线程待执行的操作为耗时操作;
启动单元,用于启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端;
执行单元,用于利用所述第一进程的UI线程开始执行所述耗时操作;
第一变更单元,用于当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
根据本申请实施例的第五方面,提供一种避免应用触发ANR的装置,包括:
确认单元,用于确认第一进程的UI线程待执行的操作为耗时操作;
执行单元,用于利用所述第一进程的UI线程开始执行所述耗时操作;
启动单元,用于在触发应用程序无响应ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端;
第一变更单元,用于当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
根据本申请实施例的第六方面,提供一种避免应用触发ANR的装置,包括:
执行单元,用于利用第一进程的UI线程执行操作;
确认单元,用于确认所述操作为耗时操作;
启动单元,用于在触发应用程序无响应ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端;
第一变更单元,用于当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
通过以上技术方案可以看出,在发生ANR之前,通过启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端,从而使得第二Activity实例对应的用户界面被显示于屏幕的最前端。此后,在UI线程执行耗时操作的过程中,由于屏幕最前端不是第一进程对应的用户界面,可以确保用户的交互事件不会进入第一进程的UI线程,从而在通过UI线程执行耗时操作的过程中,有效避免应用程序因一段时间无法响应用户的交互事件而弹出ANR对话框。
应当理解的是,以上的一般描述和后文的细节描述仅是示例性和解释性的,并不能限制本申请。
具体实施方式
这里将详细地对示例性实施例进行说明,其示例表示在附图中。下面的描述涉及附图时,除非另有表示,不同附图中的相同数字表示相同或相似的要素。以下示例性实施例中所描述的实施方式并不代表与本申请实施例相一致的所有实施方式。相反,它们仅是与如所附权利要求书中所详述的、本申请实施例的一些方面相一致的装置和方法的例子。
在本申请实施例使用的术语是仅仅出于描述特定实施例的目的,而非旨在限制本申请实施例。在本申请实施例和所附权利要求书中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其他含义。还应当理解,本文中使用的术语“和/或”是指并包含一个或多个相关联的列出项目的任何或所有可能组合。
应当理解,尽管在本申请实施例可能采用术语第一、第二、第三等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本申请实施例范围的情况下,第一信息也可以被称为第二信息,类似地,第二信息也可以被称为第一信息。取决于语境,如在此所使用的词语“如果”可以被解释成为“在……时”或“当……时”或“响应于确定”。
在一些计算机设备的操作系统(如:andriod)中,如果某应用程序在一段时间(如:5秒)内未响应用户的交互事件(如:触摸事件或键盘事件等),则操作系统会显示一个应用程序无响应(Application Not Responding,ANR)对话框,该ANR对话框用于询问用户继续等待响应还是关闭该应用程序,用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”来关闭该应用程序。一般地,应用程序运行期间出现ANR对话框对用户而言,是一种不良的使用体验。为此,开发者对程序的响应性能的设计很重要,需要尽量避免将ANR对话框显示给用户。在相关技术中,为了降低出现ANR对话框的可能性,一般不通过UI线程(UIthread/main thread)来处理耗时操作(如:数据库查询等),而是通过其他非UI线程(如:子线程、Worker线程)来处理耗时操作。然而,在实际应用中,仍然存在通过UI线程处理一些耗时操作的需求,为了在通过UI线程处理一些耗时操作的过程中避免出现ANR对话框,提出了本申请的技术方案。
图1是根据一示例性实施例示出的一种避免应用触发ANR的方法的流程。该方法可应用于计算机设备(如手机)上。如图1所示,以Android操作系统为例,所述方法可包括步骤101~104,其中:
在步骤101中,确认第一进程的UI线程待执行的操作为耗时操作。
在计算机设备上运行某目标应用程序(如网约车应用程序)时,启动上述第一进程(Process),该第一进程可以包括一个或多个线程(thread),其中,一个或多个线程中包含UI线程(也称为主线程)。UI线程负责向Android系统的UI组件(UI toolkit)分发事件(如绘制事件),即在该UI线程中,目标应用程序和Android系统的UI组件发生交互。
在一实施例中,步骤101可以通过如下过程来实现:
当第一进程的UI线程待执行的操作的类型与预先确定的至少一种耗时操作的类型一致时,确认所述操作为耗时操作。
例如,可以预先确定用户的属于耗时操作的类型包括:类型a(用于查询数据库)、类别B(用于访问特定网络)等,当第一进程待执行的事件属于上述类型之一时,则确定该第一进程接下来需要执行耗时操作。其中,第一进程的待执行操作可以通过用户的交互事件(如触摸事件或输入事件等)来触发。
在步骤102中,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端。
在一可选的实施例中,可在确定需要执行耗时操作的第一进程开始执行耗时操作之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端。也就是说,若确定第一进程的UI线程需要执行的操作为耗时操作,并不是立即通过UI线程执行该耗时操作,而是在执行耗时操作前,启动第二进程对应的第二Activity实例。
其中,第二进程为区别于上述第一进程的另一进程。第一进程和第二进程可以是同一应用程序(如网约车客户端应用程序)的两个不同进程,也可以是不同应用程序的进程。在android系统中,一个Activity实例是一个显示于屏幕上的用户界面,该用户界面上可以显示一些控件,也可以监听用户的交互事件并做出响应。
Android系统一般通过Activity栈来管理各个被启动的Activity实例。Activity实例的状态通常包括四种:Active状态、Paused状态、Stopped状态及Killed状态。其中,当一个Activity实例在Activity栈中的位置为Activity栈的顶端,则该Activity实例处于Active状态,相应地,该Activity实例对应的用户界面处于屏幕的最前端。当一个Activity实例在Activity栈中的位置为Activity栈的第二层(所述第二层位于所述Activity栈的顶端下并与所述顶端相邻)时,该Activity实例的状态叫做暂停状态(Paused),此时,该Activity实例依然与窗口管理器保持连接,其用户界面依然为可见状态。处于Stopped状态的Activity实例所对应的用户界面一般是不可见的(隐藏到后台)。系统负责管理Activity栈中的Activity实例,根据Activity实例所处的状态来改变其在栈中的位置。
参图2所示,本申请实施例中,运行第一进程之后,也可以相应启动第一进程所对应的第一Activity实例,此后,计算机设备10的屏幕上可以显示与该第一Activity实例对应的用户界面A。此时,由于第一Activity实例在Activity栈中位置为Activity栈的顶端,所以用户界面A显示于屏幕上的最前端。其中,在该用户界面A上可以包括一个或多个可触发用户交互事件的控件12。假设用户点击控件12之后触发了某种耗时操作,然而,第一进程的UI线程并没有立刻执行该耗时操作,而是启动第二进程对应的第二Activity实例,并且,第二Activity实例在Activity栈中的位置为Activity栈的顶端,而第一Activity实例的位置由原先的顶端变成的第二层。这样,当启动第二Activity实例后,计算机设备的屏幕上可以显示与该第二Activity实例对应的用户界面B,并且该用户界面B位于屏幕的最前端,用户界面B覆盖于用户界面A之上。
在步骤103中,所述第一进程的UI线程开始执行所述耗时操作。
在步骤104中,当所述UI线程执行完上述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端,从而使得上述用户界面A恢复显示于屏幕的最前端。
参图3所示,在本申请实施例中,假设第一Activity实例为Activity X,第二Activity实例为Activity Y,在UI线程执行耗时操作之前,Activity X处于Activity栈的顶端;在UI线程执行耗时操作过程中,Activity Y处于Activity栈的顶端,Activity X处于Activity栈的第二层;在UI线程执行完耗时操作后,Activity X恢复到Activity栈的顶端。
本申请实施例中,在UI线程执行耗时操作的过程中,由于屏幕最前端不是第一进程对应的用户界面A(而是另一进程对应的用户界面B),可以确保在执行耗时操作期间,用户的交互事件不会进入第一进程的UI线程,从而在通过UI线程执行耗时操作的过程中,有效避免应用程序因一段时间无法响应用户的交互事件而弹出ANR对话框。
在本申请一可选实施例中,所述第二Activity实例对应的用户界面B是覆盖于所述第一Activity实例对应的用户界面A上的透明界面。所述透明界面的透明度可以是100%,也可以是其他透明度的界面(如半透明)。其中,当用户界面B被显示与屏幕的最前端时,用户界面A并没有被隐藏到后台,而是仍然处于可见状态(即第一Activity实例的位置由原先的顶端变成的第二层),并且由于用户界面B是一种透明界面,从而使得从用户的角度来看,感觉当前屏幕显示的仍然是用户界面A。然而,从计算机设备角度来看,由于当前屏幕最前端是用户界面B,用户在屏幕上的操作所触发的交互事件并不会被用户界面A所对应的UI线程所感知,故而,也不会在执行耗时操作期间(如10秒)出现ANR对话框。当然,在其他实施例中,也可以在将用户界面B显示于屏幕最前端的同时,将用户界面A置于不可见状态。
本申请一实施例中,所述第二Activity实例对应的用户界面B中可以未包括用于触发人机交互事件的用户控件,从而,当用户界面B显示于屏幕最前端并覆盖于用户界面A之上时,用户在屏幕上无法触发交互事件,进而,避免因在一段时间内无法响应用户交互事件而产生ANR对话框。
本申请一实施例中,所述步骤104可以具体包括:
步骤1041:当所述UI线程执行完耗时操作后,所述第一进程对应的第一Activity实例向所述第二Activity实例发送目标广播,所述目标广播用于指示所述UI线程执行完耗时操作;
步骤1042:当所述第二Activity实例接收到所述目标广播后,结束所述第二Activity实例,如:通过finish()来结束Activity。
步骤1043:在所述第二Activity实例结束后,将所述第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
当然,结束第二Activity实例的方式并不限于广播方式。例如,定义一个用于指示耗时操作执行状态的值,当UI线程执行完耗时操作,去相应修改该值,当UI线程修改之后,第二Activity实例可以通过查看该值来确定耗时操作是否执行完毕,并在执行完毕后结束自己。
图4是根据一示例性实施例示出的另一种避免应用触发ANR的方法的流程。该方法可应用于计算机设备(如手机)上。如图4所示,以Android操作系统为例,所述方法可包括步骤201~204,其中:
在步骤201中,确认第一进程的UI线程待执行的操作为耗时操作。
在步骤202中,所述第一进程的UI线程开始执行所述耗时操作。
在步骤203中,在触发应用程序无响应所述ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端。
在步骤204中,当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
上述步骤201~步骤204可以参照上述步骤101~步骤104相关的实施例,在此不再赘述。
其中,图4所示的实施例与图1所示的实施例相比,其区别包括:启动第二进程对应的第二Activity实例的步骤和开始执行所述耗时操作的步骤之间的先后顺序不同。也就是说,可以在启动第二进程对应的第二Activity实例之前便开始执行所述耗时操作,只要确保能够在触发应用程序无响应所述ANR对话框之前,启动第二进程对应的第二Activity实例即可,以避免在执行耗时操作期间发生ANR。
图5是根据一示例性实施例示出的又一种避免应用触发ANR的方法的流程。该方法可应用于计算机设备(如手机)上。如图4所示,以Android操作系统为例,所述方法可包括步骤201~204,其中:
在步骤301中,第一进程的UI线程执行操作。
在步骤302中,确认所述操作为耗时操作。
在步骤303中,在触发应用程序无响应所述ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端。
在步骤304中,当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
上述步骤301~步骤304可以参照上述步骤101~步骤104相关的实施例,在此不再赘述。
其中,图5所示的实施例与图1所示的实施例相比,其区别包括:可以在第一进程的UI线程执行操作之后,确认第一进程正在执行的操作为耗时操作,随后,在触发应用程序无响应所述ANR对话框之前,启动第二进程对应的第二Activity实例,以避免在执行耗时操作期间发生ANR。
与上述避免应用触发ANR的方法的实施例对应,本申请实施例还提供了避免应用触发ANR的装置的实施例,以下将结合图6~图9进行介绍。
图6是根据一示例性实施例示出的一种电子设备的硬件结构。请参考图6,在硬件层面,该电子设备包括处理器、内部总线、网络接口、存储器(包括内存以及非易失性存储器),当然还可能包括其他业务所需要的硬件。其中,在存储器内可以存储有用以实现避免应用触发ANR的装置的相关逻辑(即计算机程序),处理器可从非易失性存储器中读取对应的计算机程序到内存中然后运行。当然,除了软件实现方式之外,本申请并不排除其他实现方式,比如逻辑器件抑或软硬件结合的方式等等,也就是说以下处理流程的执行主体并不限定于各个逻辑单元,也可以是硬件或逻辑器件。
图7是本申请实施例根据一示例性实施例示出的避免应用触发ANR的装置的框图,如图7所示,一种避免应用触发ANR的装置,包括:
确认单元501,用于确认第一进程的UI线程待执行的操作为耗时操作。
启动单元502,用于启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端。
执行单元503,用于利用所述第一进程的UI线程开始执行所述耗时操作。
第一变更单元504,用于当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
在一可选实施例中,上述确认单元501具体用于:
当第一进程的UI线程待执行的操作的类型与预先确定的至少一种耗时操作的类型一致时,确认所述操作为耗时操作。
在一可选实施例中,所述装置还包括:
第二变更单元,用于在启动第二进程对应的第二Activity实例后,将所述第一进程对应的第一Activity实例在Activity栈中的位置变更为所述Activity栈的第二层,所述第二层位于所述Activity栈的顶端下并与所述顶端相邻。
在一可选实施例中,所述第二Activity实例对应的用户界面是覆盖于所述第一Activity实例对应的用户界面上的透明界面。
在一可选实施例中,所述第二Activity实例对应的用户界面中未包括用于触发人机交互事件的用户控件。
在一可选实施例中,所述第一变更单元具体包括:
广播发送子单元,用于当所述UI线程执行完耗时操作后,所述第一进程对应的第一Activity实例向所述第二Activity实例发送目标广播,所述目标广播用于指示所述UI线程执行完耗时操作;
结束子单元,用于当所述第二Activity实例接收到所述目标广播后,结束所述第二Activity实例;
变更子单元,用于将所述第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
图8是本申请实施例根据一示例性实施例示出的避免应用触发ANR的装置的框图,如图8所示,一种避免应用触发ANR的装置,包括:
确认单元601,用于确认第一进程的UI线程待执行的操作为耗时操作。
执行单元602,用于利用所述第一进程的UI线程开始执行所述耗时操作。
启动单元603,用于在触发应用程序无响应ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端。
第一变更单元604,用于当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
图9是本申请实施例根据一示例性实施例示出的避免应用触发ANR的装置的框图,如图9所示,一种避免应用触发ANR的装置,包括:
执行单元701,用于利用第一进程的UI线程执行操作。
确认单元702,用于确认所述操作为耗时操作。
启动单元703,用于在触发应用程序无响应ANR对话框之前,启动第二进程对应的第二Activity实例,并将所述第二Activity实例在Activity栈中的位置确定为Activity栈的顶端。
第一变更单元704,用于当所述UI线程执行完所述耗时操作后,将所述第一进程对应的第一Activity实例在所述Activity栈中的位置变更为所述Activity栈的顶端。
需说明的是,本文记载的方法实施例的内容和装置实施例的内容,在不相冲突的情况下,可以互为补充。
对于装置实施例而言,由于其基本对应于方法实施例,所以相关之处参见方法实施例的部分说明即可。以上所描述的装置实施例仅仅是示意性的,其中作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本申请方案的目的。本领域普通技术人员在不付出创造性劳动的情况下,即可以理解并实施。
本领域技术人员在考虑说明书及实践这里公开的公开后,将容易想到本申请的其它实施方案。本申请旨在涵盖本申请的任何变型、用途或者适应性变化,这些变型、用途或者适应性变化遵循本申请的一般性原理并包括本申请未公开的本技术领域中的公知常识或惯用技术手段。说明书和实施例仅被视为示例性的,本申请的真正范围和精神由下面的权利要求指出。
应当理解的是,本申请并不局限于上面已经描述并在附图中示出的精确结构,并且可以在不脱离其范围进行各种修改和改变。本申请的范围仅由所附的权利要求来限制。