Android
오리엔테이션 변경
수색…
비고
활동 상태 저장 및 복원
활동이 중지되기 시작할 때 시스템은 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);
}
}
Activity가 소멸되기 전에 시스템은 해당 메소드를 호출합니다. 그런 다음 시스템은 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
에서 수행하면 모든 초기화가 완료되고 서브 클래스가 기본 구현을 사용할지 여부를 결정할 수 있으므로 편리합니다. 자세한 내용은이 stackoverflow 게시물 을 참조하십시오.
onSaveInstanceState
와 onRestoreInstanceState
는 함께 호출 할 수 없습니다. 안드로이드는 활동이 파괴 될 가능성이있을 때 onSaveInstanceState()
호출합니다. 그러나 onSaveInstanceState
가 호출되었지만 활동이 삭제되지 않고 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
에서 저장된 상태에서 데이터를 가져올 수 있습니다.
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;
}
}
이 접근법은 활동 라이프 사이클 동안 조각이 파손되지 않도록합니다. 대신 Fragment Manager에 유지됩니다. 자세한 내용은 Android 공식 문서를 참조 하십시오 .
이제 조각을 만들기 전에 조각이 태그에 의해 이미 존재하는지 확인할 수 있습니다. 단편 조각은 구성 변경 사항 전체에서 상태를 유지합니다. 자세한 내용은 런타임 변경 처리 설명서를 참조하십시오 .
잠금 화면 방향
Android 애플리케이션의 화면 (액티비티) 화면 방향 변경을 잠 그려면 AndroidManifest.xml 에서 <activity>
의 android:screenOrientation
속성을 설정하기 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">
이제 이러한 구성 중 하나가 변경되면 활동이 다시 시작되지 않고 대신 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
에 대한 가져 오기를 볼 수 있습니다 (두 가지 모두 없어야 함).
프로그래밍 방식으로 화면 회전 잠금
개발하는 동안 코드의 특정 부분에서 장치 화면을 잠 그거나 잠금을 해제하는 것이 매우 유용 할 수 있습니다 .
예를 들어 정보가있는 대화 상자를 표시하는 동안 개발자는 대화 상자가 닫히지 않도록 화면의 회전을 잠그고 대화 상자를 닫을 때 현재 활동을 다시 작성하여 다시 열지 못하게 할 수 있습니다.
다음을 수행하여 매니페스트에서 로테이션 잠금을 얻을 수는 있습니다.
<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)