从发送业务数据的活动和屏幕旋转屏幕、业务、数据

2023-09-12 05:35:31 作者:國民撩漢壹把手

我使用一个Intent服务执行的操作,需要回传给启动它的操作的结果的活动。

I am using an Intent Service that performs an action and needs to pass back to the activity that started it the results of the action.

我已经经历了几十个类似的职位搜索,但据我所知,所有的解决方案,我发现有一个问题。他们不处理好屏幕旋转。假设一个活动开始的意图服务,该服务需要10秒来执行的动作,而在这10秒,屏幕被旋转。该活动被销毁并创建一个新的。

I've searched through dozens of similar posts but as far as i can tell, all solutions i found have a problem. They don't handle well screen rotation. Suppose an activity starts the Intent Service, the service takes 10 seconds to perform the action, and during those 10 secs, the screen gets rotated. The activity gets destroyed and a new one is created.

使用接收器:它创建一个内存泄漏,因为接收器绑定到必须销毁活动,使该活动永远不会被破坏。 使用广播:你需要注册一个监听器,和未注册的听众前的活性被破坏。如果广播消息到达后,听众是未注册的,而新的活动的侦听器已注册之前,将永远不会被接收的消息。 使用消息:同接收器 使用共享preferences /数据库监听器:同广播

我想出了,是有服务将结果保存在preference文件,该活动定期检查该解决方案(可以说每200ms)在preference文件的变化。因此,当屏幕旋转时,活动停止检查,并重新创建时再次开始。如果结果被送到在两者之间,它仍然得到的(重建)的活性。不过,好像这会消耗CPU和不必要的执行从SD卡读取。

The solution i came up with, is having the service save the result in a preference file, and the activity checking regularly (lets say every 200ms) for a change in the preference file. Thus, when the screen rotates, the activity stops checking, and starts again when recreated. If the result was delivered in between, it still gets to the (recreated) activity. However, it seems as though this consumes cpu and performs unnecessary reads from the SD card.

另一种解决方案是让服务结果保存在preference文件/数据库,并将它保存它时的全局变量。该活动有一个监听到preference文件/数据库。注册监听器之前,它会检查全局变量,看看结果是屏幕旋转过程中把(全局变量< currentTimeMillies()),如果属实,得到的结果,如果没有,将注册侦听器。由于结果可能检查和登记之间放,这必须在其中活动持有锁该服务必须获得把结果的块内完成的。这也将工作,但它是太复杂了。

Another solution would be to have the service save the result in preference file/database and set a global variable to the time it saved it. The activity has a listener to the preference file/database. Before registering the listener, it checks the global variable to see if the result was put during the screen rotation (global var < currentTimeMillies()) and if true, gets the result, if not, registers the listener. Since the result might be put between the check and the registration, this has to be done inside a block in which the activity holds a lock that the service must acquire to put the result. This would also work, but it is way too complicated.

有没有做这件事,幸存的一个屏幕旋转的更简单,更优雅的方式?

Is there a simpler and more elegant way of doing it, surviving a screen rotation?

推荐答案

有一个在我回答这个问题:

Have a look at my answer to this question:

How服务和活动(和它的子活动)之间的处理IPC?

也许这会给你一个想法。

Perhaps that will give you an idea.

修改(添加以下建议):

另一种方法是使用哪个你在活动创建一个接收机。在一个屏幕旋转,操作系统将调用onRetainNonConfigurationInstance(),您可以返回接收器实例,它会被传递给新的活动(见getLastNonConfigurationInstance())。注意:这些方法已经去precated在4.0,你可以用一个片段和setRetainInstance()来实现类似的行为

Another approach would be to use a Receiver which you create in the Activity. On a screen rotation, the OS will call onRetainNonConfigurationInstance() where you can return the Receiver instance and it will get handed off to the new Activity (see getLastNonConfigurationInstance()). NOTE: These methods have been deprecated in 4.0 and you can use a Fragment and setRetainInstance() to achieve similar behaviour.