3

関連する質問:


これは、アクティビティで発生した奇妙な動作です。

ポートレートモード(ノーマルです)

  1. 画面ロックを押しますActivity: onPause()
  2. 画面のロックを解除しますActivity: onResume()

ランドスケープモード(おかしい)

  1. 画面ロックを押すと、ポートレートレイアウトActivity: onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()が読み込まれます。
  2. 画面のロックを解除し、 LandscapeレイアウトActivity: onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()を読み込みます。

私が期待するものは次のとおりです。

ポートレートモード:(同上)

横向きモード: (縦向きモードのように動作する必要があります)

  1. 画面ロックを押しますActivity: onPause()
  2. 画面のロックを解除しますActivity: onResume()

だから私の質問:

  • アクティビティがこのように動作するのはなぜですか?
  • アクティビティはどのように動作しますか?

私の質問の原文の説明:

電話のロック画面ボタンを押しているときに、アクティビティがランドスケープ モードのときに、(Eclipse に出力したデバッグ メッセージで) アクティビティがポートレート モードに再作成されていることに気付きました (画面がすべて黒くなっている間、もちろん)。次に、ロック画面ボタンをもう一度押して画面のロックを解除すると、アクティビティが破棄され、ポートレートに再作成されました。

私が覚えているように (100% 確実ではありませんが)、私が期待しているのは、ポートレート モードの場合と同様に、横向きモードで画面をロックしている間、私のアクティビティはonSaveInstanceState()とのみを受ける必要があることです。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 の現在の状態を (必要なすべてのデータを) 保存する必要があります。

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 に答える