Using the Android Application class to persist data
我正在开发一个相当复杂的Android应用程序,它需要关于应用程序的大量数据(我说总共大约500KB - 这对于移动设备来说是否很大?)。 据我所知,应用程序中的任何方向更改(在活动中,更准确地说)会导致活动的完全破坏和重新创建。 根据我的发现,Application类没有相同的生命周期(即,所有意图和目的,它总是被实例化)。 将状态信息存储在应用程序类中然后从Activity引用它是否有意义,或者由于移动设备上的内存限制,这通常不是"可接受的"方法? 我真的很感激有关这个主题的任何建议。 谢谢!
-
请记住,如果您的应用程序进入后台,您的应用程序中的数据仍然可以删除,因此这不是持久保存您希望能够获得的数据的解决方案。 它只是一种不必经常重建昂贵对象的方法。
-
梅拉; 我不认为该应用程序"通常"被删除(但是,正如有人在此主题中稍后指出的那样,它"可以")。 我可能会采用某种类型的"混合"方法来使用应用程序来存储和加载数据,但是然后在清单文件中的活动上使用"android:orientation"属性来覆盖正常的行为 拆除并重建活动。 当然,所有这些都假设应用程序可以确定它何时被销毁,以便可以保留数据。
我认为500kb不会是那么大的交易。
你所描述的正是我如何解决我在活动中丢失数据的问题。我在Application类中创建了一个全局单例,并且能够从我使用的活动中访问它。
如果将要使用很多,您可以在Global Singleton中传递数据。
1 2 3 4
| public class YourApplication extends Application
{
public SomeDataClass data = new SomeDataClass();
} |
然后在以下任何活动中调用它:
1 2
| YourApplication appState = ((YourApplication)this.getApplication());
appState.data.UseAGetterOrSetterHere(); // Do whatever you need to with the data here. |
我在我的博客文章"Global Singleton"一节中讨论它。
-
不幸的是,该地址不再提供相关的博客文章。
-
我一直在我的网站上移动东西。在修复之前,你可以在archive.org上找到它:web.archive.org/web/20130818035631/http://www.bryandenny.com/…
-
我知道这是一个老帖子,但我遇到了一个问题,这可能会解决,但是这个类需要在清单中以某种方式声明,不是吗?我不能上课,所以觉得这就是我所缺少的......
-
@ZivKesten如何将manifest =属性添加到清单中的应用程序标签?
-
@mgc谢谢你已经有一段时间了,是的,这就是我最终解决的问题,也是我在需要的地方创建了该类的实例,给它带有一个转换为此类的getApplicationContext()
-
应用程序永远不会被销因为正常的单身人士课程会被摧毁!
-
布莱恩,我将不同意应有的尊重。如果处理的应用程序被操作系统杀死,应用程序类将丢失数据(在内存不足的情况下)。
-
Application对象可能会被销毁,除非getter-method重新创建单例,否则如果你运气不好,你会有一个空引用错误。 developerphil.com/dont-store-data-in-the-application-object
那些依靠Application实例的人是错误的。一开始,只要整个应用程序进程存在,似乎Application就存在,但这是一个不正确的假设。
操作系统可能会根据需要终止进程。所有流程分为5个级别的"killability",在doc中指定。
因此,例如,如果您的应用由于用户接听来电而进入后台,那么根据RAM的状态,操作系统可能(或可能不会)终止您的进程(破坏Application实例过程)。
我认为更好的方法是将您的数据保存到内部存储文件,然后在您的活动恢复时读取它。
更新:
我得到了很多负面反馈,所以是时候加上澄清了。 :)好吧,最初我真的使用了一个错误的假设,即状态对应用程序非常重要。但是,如果您的应用程序没问题,有时状态会丢失(可能是某些图像只会重新读取/重新加载),那么将其保留为Application的成员就可以了。
-
如果申请被杀,那么谁在乎,对吧?申请已经不见了。据我了解,Android将回收包含活动等内存的进程。如果包含应用程序的进程被终止(如果Android甚至会这样做?),那就像杀死应用程序一样。用户需要再次启动应用程序,此时,谁在乎?这是该应用程序的新实例。
-
这对我们的制作来说是一个不可思议的惊喜。相信我杀死Android的过程,它只取决于RAM状态和文档中描述的其他因素。这对我们来说是一场噩梦所以我只是分享我的真实经历。好吧,我们在模拟器上没有这个,但在现实世界中,一些设备"应用"过载,因此杀死后台进程是正常情况。是的,如果用户然后决定将应用程序放到前台 - 操作系统将恢复其堆栈,包括Application实例,但是除非您持久保存,否则不会有您依赖的静态数据。
-
我想我可能会采用混合方法。我已经知道了覆盖方向变化的明显技巧(具有其他好处)。由于应用程序是游戏,我不确定在启动之间保持数据是否"足够";虽然它可能不会非常困难,因为大多数数据都可以序列化(尽管我不希望在每个方向更改之间序列化和反序列化)。我非常感谢输入。我不会说那些依赖于App实例的是"错误的"。很大程度上取决于应用:)。
-
@Arhimed你太过粗略地概括了你的答案。并根据您的假设建议一种狭隘的方法。错误假设:静态变量中保存的数据需要在应用程序的会话中保留。可能存在许多用例,其中数据是微不足道的并且不需要立即持久化。
-
我有大约1mb数据,结构复杂。当设备超负荷工作时,序列化/反序列化可能花费我2-3秒。在活动之间保存/加载的想法花费了太多时间。我使用应用程序作为存储。当然,我存储在应用程序实例中的数据类检查了每个元数据 - 数据是否仍然存活或必须加载。所以Dave必须:1。提供加载/保存完成2.保持应用程序中的数据。 3.用于访问数据的三重检查逻辑。
-
这是正确且更安全的答案。
-
这是对不同问题的正确答案。 如果您只保留Application会话的数据,那么在Singleton中或在Application类中的对象中保持100%是正确的。 如果仅用于会话信息,您应该总是更喜欢在内存而不是磁盘中持久存储。 坚持使用磁盘不仅速度慢,而且会更快地耗尽用户的硬件。
如果要访问活动之外的"Global Singleton"并且不希望通过所有涉及的对象传递Context来获取单例,则可以在应用程序类中定义一个静态属性,该属性包含对自己的引用。只需在onCreate()方法中初始化属性即可。
例如:
1 2 3 4 5 6 7 8
| public class ApplicationController extends Application {
private static ApplicationController _appCtrl;
public static ApplicationController getAppCtrl()
{
return _appCtrl;
}
} |
因为Application的子类也可以获取资源,所以只需在定义返回它们的静态方法时就可以访问它们,例如:
1 2 3 4
| public static Resources getAppResources()
{
return _appCtrl.getResources();
} |
但是在传递Context引用时要非常小心,以避免内存泄漏。
-
您忘了注意,您必须在清单中为要实例化的类添加android:name ="。ApplicationController"xml属性应用程序标记。
-
您实际上不需要扩展Application来执行此操作。 您可以在任何类中声明静态成员变量来执行此操作。
戴夫,这是什么类型的数据?如果它是与整个应用程序相关的一般数据(例如:用户数据),则扩展Application类并将其存储在那里。如果数据属于Activity,则应使用onSaveInstanceState和onRestoreInstanceState处理程序在屏幕旋转时保留数据。
-
如果数据真的很大,可以存储在包裹中怎么办? 这就是我得到的:android.os.TransactionTooLargeException:数据包大小838396字节
您实际上可以覆盖方向功能,以确保不会销毁和重新创建您的活动。看这里。
-
你可以做很多事情。这并不意味着他们是好主意。这不是一个好主意。
-
通过更改屏幕方向进行测试是确保您的应用完成Android假定的操作的最简单方法。
您可以创建Application类并将所有数据保存在该calss中,以便在应用程序的任何位置使用。