Android
オリエンテーションの変更
サーチ…
備考
アクティビティ状態の保存と復元
アクティビティーが停止し始めると、システムはonSaveInstanceState()
呼び出して、アクティビティーがキーと値のペアの集合で状態情報をonSaveInstanceState()
できるようにします。このメソッドのデフォルト実装では、 EditText
ウィジェット内のテキストやListView
スクロール位置など、アクティビティのビュー階層の状態に関する情報が自動的に保存されます。
アクティビティの追加の状態情報を保存するには、 onSaveInstanceState()
を実装し、Bundleオブジェクトにキーと値のペアを追加する必要があります。例えば:
public class MainActivity extends Activity {
static final String SOME_VALUE = "int_value";
static final String SOME_OTHER_VALUE = "string_value";
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
// Save custom values into the bundle
savedInstanceState.putInt(SOME_VALUE, someIntValue);
savedInstanceState.putString(SOME_OTHER_VALUE, someStringValue);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
}
アクティビティが破棄される前に、システムはそのメソッドを呼び出します。その後、システムはonRestoreInstanceState
を呼び出して、バンドルから状態を復元することができます。
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
someIntValue = savedInstanceState.getInt(SOME_VALUE);
someStringValue = savedInstanceState.getString(SOME_OTHER_VALUE);
}
インスタンスの状態は、標準のActivity#onCreateメソッドでも復元できますが、初期化がすべてonRestoreInstanceState
たことを保証し、サブクラスがデフォルトの実装を使用するかどうかを決めるonRestoreInstanceState
で行うのが便利です。詳細はこのstackoverflow postを参照してください。
onSaveInstanceState
とonRestoreInstanceState
はonSaveInstanceState
にonRestoreInstanceState
はできません。 Androidは、アクティビティが破棄される可能性がある場合にonSaveInstanceState()
呼び出します。ただし、 onSaveInstanceState
が呼び出されてもアクティビティが破棄されず、結果としてonRestoreInstanceState
が呼び出されないonRestoreInstanceState
があります。
フラグメント状態の保存と復元
フラグメントには、状態を保存する必要があるときに呼び出されるonSaveInstanceState()
メソッドもあります。
public class MySimpleFragment extends Fragment {
private int someStateValue;
private final String SOME_VALUE_KEY = "someValueToSave";
// Fires when a configuration change occurs and fragment needs to save state
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(SOME_VALUE_KEY, someStateValue);
super.onSaveInstanceState(outState);
}
}
次に、 onCreateView
でこの保存された状態からデータを取り出すことができonCreateView
:
public class MySimpleFragment extends Fragment {
// ...
// Inflate the view for the fragment based on layout XML
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_simple_fragment, container, false);
if (savedInstanceState != null) {
someStateValue = savedInstanceState.getInt(SOME_VALUE_KEY);
// Do something with value if needed
}
return view;
}
}
フラグメント状態を適切に保存するには、構成の変更時にフラグメントを不必要に再作成していないことを確認する必要があります。これは、既存のフラグメントが既に存在する場合に、それらを再初期化しないように注意することを意味します。アクティビティで初期化されているフラグメントは、コンフィグレーションの変更後にタグで参照する必要があります。
public class ParentActivity extends AppCompatActivity {
private MySimpleFragment fragmentSimple;
private final String SIMPLE_FRAGMENT_TAG = "myfragmenttag";
@Override
protected void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) { // saved instance state, fragment may exist
// look up the instance that already exists by tag
fragmentSimple = (MySimpleFragment)
getSupportFragmentManager().findFragmentByTag(SIMPLE_FRAGMENT_TAG);
} else if (fragmentSimple == null) {
// only create fragment if they haven't been instantiated already
fragmentSimple = new MySimpleFragment();
}
}
}
これは、トランザクション内のアクティビティにフラグメントを配置するたびに、参照用のタグを含めるように注意する必要があります。
public class ParentActivity extends AppCompatActivity {
private MySimpleFragment fragmentSimple;
private final String SIMPLE_FRAGMENT_TAG = "myfragmenttag";
@Override
protected void onCreate(Bundle savedInstanceState) {
// ... fragment lookup or instantation from above...
// Always add a tag to a fragment being inserted into container
if (!fragmentSimple.isInLayout()) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragmentSimple, SIMPLE_FRAGMENT_TAG)
.commit();
}
}
}
この単純なパターンでは、フラグメントを適切に再利用して構成の変更を元に戻すことができます。
断片を保持する
多くの場合、単に断片を使用してアクティビティーを再作成するときの問題を回避できます。ビューと状態がフラグメント内にある場合、アクティビティが再作成されたときにフラグメントを保持することは簡単にできます:
public class RetainedFragment extends Fragment {
// data object we want to retain
private MyDataObject data;
// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment when activity is re-initialized
setRetainInstance(true);
}
public void setData(MyDataObject data) {
this.data = data;
}
public MyDataObject getData() {
return data;
}
}
このアプローチは、アクティビティライフサイクル中にフラグメントが破壊されないようにします。代わりにフラグメントマネージャーの内部に保持されます。詳細については、Androidの公式ドキュメントをご覧ください 。
これでフラグメントを作成する前にそのフラグメントがタグですでに存在するかどうかを確認することができ、フラグメントは構成の変更を超えてその状態を保持します。詳細については、ランタイム変更の処理ガイドを参照してください 。
ロック画面の方向
Androidアプリケーションの画面(アクティビティ)の画面の向きを変更したい場合は、 AndroidManifest.xml内の<activity>
のandroid:screenOrientation
プロパティを設定するだけです。
<activity
android:name="com.techblogon.screenorientationexample.MainActivity"
android:screenOrientation="portrait"
android:label="@string/app_name" >
<!-- ... -->
</activity>
これで、アクティビティは常に「 ポートレート 」モードで表示されます。
構成変更の手動管理
アプリケーションが特定の構成変更中にリソースを更新する必要がなく、アクティビティの再起動を回避する必要のあるパフォーマンス制限がある場合は、アクティビティが構成変更自体を処理することを宣言することができます。アクティビティ。
ただし、このテクニックは構成変更のために再起動を避け、ほとんどのアプリケーションでは推奨されない場合は最後の手段と考える必要があります。このアプローチをとるには、 AndroidManifest.xml内のアクティビティにandroid:configChanges
ノードを追加する必要があります。
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="@string/app_name">
これらの設定の1つが変更されると、アクティビティは再起動されず、代わりにonConfigurationChanged()
呼び出しを受け取ります。
// Within the activity which receives these changes
// Checks the current device orientation, and toasts accordingly
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
変更文書の処理を参照してください。アクティビティでどのような設定変更を処理できるかについては、 android:configChangesのドキュメントとConfigurationクラスを参照してください。
AsyncTaskの処理
問題:
-
AsyncTask
起動後に画面の回転があると、所有アクティビティが破棄されて再作成されます。 -
AsyncTask
終了すると、それ以上有効ではないUIが更新されます。
溶液:
ローダーを使用すると、活動の破壊/再作成を簡単に克服することができます。
例:
主な活動:
public class MainActivity extends AppCompatActivity
implements LoaderManager.LoaderCallbacks<Bitmap> {
//Unique id for the loader
private static final int MY_LOADER = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoaderManager loaderManager = getSupportLoaderManager();
if(loaderManager.getLoader(MY_LOADER) == null) {
loaderManager.initLoader(MY_LOADER, null, this).forceLoad();
}
}
@Override
public Loader<Bitmap> onCreateLoader(int id, Bundle args) {
//Create a new instance of your Loader<Bitmap>
MyLoader loader = new MyLoader(MainActivity.this);
return loader;
}
@Override
public void onLoadFinished(Loader<Bitmap> loader, Bitmap data) {
// do something in the parent activity/service
// i.e. display the downloaded image
Log.d("MyAsyncTask", "Received result: ");
}
@Override
public void onLoaderReset(Loader<Bitmap> loader) {
}
}
AsyncTaskLoader:
public class MyLoader extends AsyncTaskLoader<Bitmap> {
private WeakReference<Activity> motherActivity;
public MyLoader(Activity activity) {
super(activity);
//We don't use this, but if you want you can use it, but remember, WeakReference
motherActivity = new WeakReference<>(activity);
}
@Override
public Bitmap loadInBackground() {
// Do work. I.e download an image from internet to be displayed in gui.
// i.e. return the downloaded gui
return result;
}
}
注意:
v4互換ライブラリを使用するかどうかは重要ですが、コンパイルエラーが発生するため、一部と他の一部を使用しないでください。確認するには、 android.support.v4.content
とandroid.content
両方のインポートを確認してください。
プログラムで画面の回転をロックする
開発中に、コードの特定の部分でデバイス画面をロック/ロック解除するのに非常に役立つことがよくあることはよくあることです 。
例えば、情報を持つDialogを表示している間、開発者は画面の回転をロックしてダイアログが消されないようにするため、現在のアクティビティを再構築しないようにすることができます。
次のようにしてマニフェストからローテーションロックを達成することができます。
<activity
android:name=".TheActivity"
android:screenOrientation="portrait"
android:label="@string/app_name" >
</activity>
次のようにすれば、プログラムでも同様に実行できます。
public void lockDeviceRotation(boolean value) {
if (value) {
int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
}
}
そして、次のように呼び出して、デバイスの回転をロックし、ロックを解除します
lockDeviceRotation(true)
そして
lockDeviceRotation(false)