Android 应用程序在方向改变时重置,最好的处理方法是什么?
所以我正在制作一个基本的国际象棋应用程序来玩弄android编程的一些不同元素,到目前为止我学到了很多东西,但这次我迷失了。
当模拟器的方向改变时,活动将被重置。根据我的研究,只要应用程序暂停/中断,即会发生同样的事情。更换键盘、打电话、按主页键等。
显然,让国际象棋游戏不断重置是不可行的,所以我再次发现自己需要学习如何解决这个问题。
我的研究提出了一些主要内容,覆盖 Activity 中的 onPaused 方法、监听 Manifest 中的方向、键盘更改(通过 android:configChanges)、使用 Parcelables 或序列化。
我查了很多使用 Pacelables 的示例代码,但说实话,这太混乱了。也许明天以新的眼光回来会有所帮助,但现在我对 Parcelables 的了解越多,它就越没有意义。
我的应用程序使用一个 Board 对象,它有 64 个单元对象(在 8x8 2D 数组中),每个单元都有一个 Piece 对象,如果空间为空,则可以是实际的块,也可以为 null。假设我使用 Parcelable 或 Serialization,我假设我必须对每个类、Board、Cell 和 Piece 进行 Parcelize 或 Serialize。
首先,也是最重要的,可打包或序列化是否是解决此问题的正确选择?如果是的话,首选 Parcelable 还是 Serialized?我假设三个对象中的每一个都必须被打包/序列化是否正确?最后,有人有一个简单易懂的 Parcelable 教程的链接吗?任何可以帮助我理解并在我的应用程序进一步扩展时停止进一步头痛的事情。
任何帮助将不胜感激。
So I am making a basic chess app to play around with some various elements of android programming and so far I am learning a lot, but this time I am lost.
When the orientation of the emulator changes the activity gets reset. Based on my research the same thing will happen anytime the application is paused/interrupted, ie. keyboard change, phone call, hitting the home key etc.
Obviously, it is not viable to have a chess game constantly reset, so once again I find myself needing to learn how to fix this problem.
My research brings up a few main things, overriding the onPaused method in my Activity, listening for Orientation, Keyboard changes in my manifest (via android:configChanges), using Parcelables, or Serialization.
I have looked up a lot of sample code using Pacelables, but to be honest it is too confusing. Maybe coming back tomorrow with fresh eyes will be beneficial, but right now the more I look at Parcelables the less sense it makes.
My application utilizes a Board object, which has 64 Cell Objects(in an 8x8 2D array), and each cell has a Piece Object, either an actual piece or null if the space is empty. Assuming that I use either Parcelable or Serialization I am assuming that I would have to Parcelize or Serialize each class, Board, Cell, and Piece.
First and foremost, is Parcelable or Serialization even the right thing to be looking at for this problem? If so is either Parcelable or Serializable preferred for this? And am I correct in assuming that each of the three objects would have to be Parceled/Serialized? Finally, does anybody have a link to a simple to understand Parcelable tutorial? Anything to help me understand, and stop further headaches down the road when my application expands even further.
Any help would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在您的清单中标签,您可以添加 android:configChanges="orientation|keyboardHidden",这将阻止 Activity 重新加载,并在方向更改或键盘隐藏时调用 onConfigurationChanged() 。
如果您需要在发生这些事件时进行调整,则可以在 Activity 中重写 onConfigurationChanged()(如果您所需要做的不是将属性添加到清单中)。
像这样的东西:
工作得很好。
in your manifest in the <Activity> tag, you can add android:configChanges="orientation|keyboardHidden", this will stop the activity from reloading and call onConfigurationChanged() instead when the orientation is changed or the keyboard is hidden.
If you need to make adjustments when either of these events happen, you can override onConfigurationChanged() in your activity, if not all you have to do is add the property to the manifest.
Something like:
works perfectly well.
Android 处理事件的默认方式是重新创建 Activity。基本上,您正确处理一个流程并且一切正常,无需担心手动处理这些事情。
应用程序基础知识对 Activity 生命周期有完整的概述,但是简而言之,您希望在 onSaveInstanceState() 方法中保存 Activity 状态,并使用 onCreate(Bundle savingInstanceState) 中获得的 Bundle 来恢复应用程序状态。
如果您想将类存储在 Bundle 中,最好的选择是实现 Parcelable 界面。然后,为了保存您的状态,您只需执行以下操作:
在 onCreate 方法中,您只需执行以下操作:
当然,您可以将对象转换为 Bundle 已包含的普通数组表示形式,并跳过实现 Parcelable 接口。基本上向您的对象添加一个方法 toArray() 和一个静态方法 fromArray()。好吧,玩一玩,看看哪个更适合你。
Androids default way of handling the events is to recreate the activity. Basically you handle one process correctly and everything works, no need to worry about handling those things manually.
The Application Fundamentals has a complete overview of the activity life cycle, but in short you want to save your activity state in the onSaveInstanceState() method and use the Bundle you get in the onCreate(Bundle savedInstanceState) to restore your application state.
If you want to store your classes in the Bundle your best bet is to implement the Parcelable interface. Then to save your state you do:
and in the onCreate method you simply do:
Of course you could just convert your objects into normal array representations that the Bundle can already contain and just skip implementing the Parcelable interface. Basically add a method toArray() to your object and a static method fromArray(). Well, play around and see which suits you better.
或者将此行粘贴到 OnCreate 中,这样它就不会旋转。问题解决了。
Or stick this line in your OnCreate so it doesn't roate. Problem solved.
重写 Activity 类中的 onRetainNonConfigurationInstance。
在此方法中,您必须返回一个对象,只需将游戏的状态捆绑在一个状态对象中,然后在此方法中返回它即可。确保这只是一个状态对象,我的意思是它不应该包含其中包含的活动、视图等的句柄,否则会发生内存泄漏。
在 onCreate 方法中调用 getLastNonConfigurationInstance 来获取对象。
你不必担心实现细节(序列化),android 会处理这个问题。
如果您尚未确保已在清单中将启动模式设置为 singleTask 或 singleInstance,具体取决于哪种方式更适合您的需求。默认情况下,如果有人回家然后返回您的应用程序,它会启动该活动的新副本,如果没有针对单个实例进行处理或配置,您将获得运行的游戏活动的多个副本。
Override onRetainNonConfigurationInstance in your Activity class.
In this method you must return an object, just bundle up your game's state in a single state object and return it in this method. Make sure this is only a state object, by that i mean it should have no handles to an activity, view, etc. contained within it or you'll get memory leaking.
In your onCreate method call getLastNonConfigurationInstance to get the object back.
You don't have to worry about the implementation details (the serialization) android takes care of that.
If you haven't already make sure you've set your Launch Mode in the manifest to either singleTask or singleInstance depending on which fits your needs better. By default if someone hits home and then comes back to your application it launches a new copy of the activity, if not handled or configured for single instance you'll get multiple copies of your game activity running.
当您保存棋盘状态时,创建一个
int[64]
并在每个位置存储相应的棋子。所以 0=空,1=白棋子,2=白骑士,等等...当您加载棋盘状态时,迭代数组并在适当的位置创建适当的棋子对象。
您可以将 int[64] 转换为字符串以存储在 SharedPreferences 中,或者将其与 Parcelable 等一起使用。仅存储您需要的最少数据。
When you save the board state, make an
int[64]
and at each position store the corresponding piece. So 0=empty, 1=white pawn, 2=white knight, etc...When you load the board state, iterate through the array and create the appropriate piece objects at the appropriate locations.
You can convert the int[64] to a string to store in SharedPreferences, or use it with a Parcelable or whatever. Only store the minimum data you need.