サーチ…


備考

リファレンス: https : //guides.codepath.com/android/Handling-Configuration-Changes#references

アクティビティ状態の保存と復元

アクティビティーが停止し始めると、システムは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を参照してください。

onSaveInstanceStateonRestoreInstanceStateonSaveInstanceStateonRestoreInstanceStateはできません。 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.contentandroid.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) 


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow