3

相关问题:


这是我在活动中遇到的一种奇怪行为。

人像模式(正常)

  1. 按屏幕锁定,Activity: onPause();
  2. 解锁屏幕,Activity: onResume().

横向模式(很奇怪)

  1. 按屏幕锁定,Activity: onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()加载纵向布局;
  2. 解锁屏幕Activity: onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()并加载横向布局。

我期望的是:

人像模式:(同)

横向模式:(应该像纵向模式一样)

  1. 按屏幕锁定,Activity: onPause();
  2. 解锁屏幕,Activity: onResume().

所以我的问题:

  • 为什么我的活动会这样?
  • 您的活动表现如何?

我的问题的原文描述:

当我按下手机的锁定屏幕按钮时,当我的活动处于横向模式时,我注意到(在我输出到 Eclipse 的调试消息中)活动被重新创建为纵向模式(当屏幕全黑时,当然)。然后,当我再次按下锁定屏幕按钮以解锁屏幕时,活动被破坏并再次重新创建为其肖像。

我记得(虽然不是 100% 肯定),我期望的是,我的 Activity 应该只经历onSaveInstanceState()and onPause(),而在横向模式下锁定屏幕,就像它在纵向模式下所做的那样。而不是将活动重新创建为纵向并再次返回到横向。

是不是我的手机搞砸了什么?我怎样才能让它恢复正常?

谢谢!


感谢大家为这个问题做出贡献。特别感谢@HoanNguyen 在他的设备中为我进行的测试。特别感谢@Raghunandan 与我就这个问题进行了深入讨论。

总结到目前为止大家的贡献,我有以下结论:

1. 这是正常现象。

看来,在手机上,处于横向模式的正在运行的活动在屏幕锁定时切换到纵向模式是正常行为。至少到目前为止,在经过测试的手机上是这样。所以我们必须确保我们的生命周期函数能够始终优雅地处理这种变化。

2.猜猜这是因为锁定屏幕中的“默认方向”。

我们没有关于此问题的文档或许多资源。但是假设正在运行的活动在屏幕锁定时切换回设备的“默认方向”,因为在大多数设备中锁定的屏幕是纵向的,这是非常合乎逻辑的。

进一步研究:

我只是想知道如果我们有一个横向锁定屏幕,活动会如何表现?

4

2 回答 2

2

您可以阻止活动在方向更改时重新启动,但这通常是一个非常糟糕的主意。

Android 文档中有一个关于使用此注释处理运行时更改的部分:

注意:自己处理配置更改会使使用替代资源变得更加困难,因为系统不会自动为您应用它们。当您必须避免由于配置更改而重新启动并且不建议用于大多数应用程序时,应将此技术视为最后的手段。

如果您不需要备用资源并且更重要的是有性能要求,Android 通常只建议您禁止重新创建轮换。在大多数情况下,设计良好的应用程序不需要这样做。

如果您坚持走抑制默认 Android 行为的道路,我会修改 Raghunandan 的代码并包含屏幕尺寸属性。从 API 级别 13 开始,屏幕尺寸会随着方向的变化而变化。因此,除非您只针对 API 12 及以下版本,否则您必须包含 screenSize。

<activity android:name=".MyActivity"
      android:configChanges="orientation|screenSize"
      android:label="@string/app_name">
于 2013-03-26T20:40:49.900 回答
0

避免活动重新启动

<activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"//add tthis in manifest
      android:label="@string/app_name">

http://developer.android.com/guide/topics/resources/runtime-changes.html

在正常情况下,当您的屏幕锁定时,您的活动会暂停,而当屏幕解锁时,活动会恢复。

锁屏时的一个问题是:当前Activity如果发现内存不足可能会被系统强行停止,而不是把Activity移到后台。在这种情况下,我们应该保存(所有必要的数据)活动的当前状态。

将数据保存在 onSaveInstanceState() 并恢复数据 onRestoreInstanceState()。

@Override
 public void  onSaveInstanceState(Bundle outState)
 {
  Log.v("$````$", "In Method: onSaveInstanceState()");
  //if necessary,set a flag to check whether we have to restore or not
  //handle necessary savings…
 }

@Override
public void onRestoreInstanceState(Bundle inState)
{
  Log.v("$````$", "In Method: onRestoreInstanceState()");
  //if any saved state, restore from it…
}

在你的 onCreate()

IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);

mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter); //register


public class ScreenReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent)
   {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
        {    
              Log.v("$$$$$$", "In Method:  ACTION_SCREEN_OFF");
              // onPause() will be called.
        }
        else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
        {
              Log.v("$$$$$$", "In Method:  ACTION_SCREEN_ON");
              //onResume() will be called.
              //Better check for whether the screen was already locked
              // if locked, do not take any resuming action in onResume()
              //Suggest you, not to take any resuming action here.       
        }
        else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT))
        {
              Log.v("$$$$$$", "In Method:  ACTION_USER_PRESENT"); 
              //Handle resuming events
        }
  }

在你的 onDestroy

  @Override
  public void onDestroy()
  {
        super.onDestroy();
        Log.v("$$$$$$", "In Method: onDestroy()");

        if (mReceiver != null)
        {
              unregisterReceiver(mReceiver); //unregister 
              mReceiver = null;
        }          

  }
于 2013-03-26T19:36:49.007 回答