백 스택에서 재개에 대한 조각
Android 2.2에서 Fragments를 사용하기 위해 외부 패키지를 사용하고 있습니다. 프래그먼트를 사용하고 그들 사이에 전환을 백 스택에 추가 할 때, 활동의 onResume과 동일한 동작을 달성하고 싶습니다. 즉, 프래그먼트가 "전경"(사용자에게 표시됨)으로 이동 한 후 백 스택, 프래그먼트 내에서 사용을 활성화하고 싶습니다 (예 : 공유 UI 리소스에서 특정 변경을 수행하기 위해).
프래그먼트 프레임 복제가 있다고 말합니다. 호스팅 달성하기위한 좋은 관행이?
더 나은 솔루션이 없기 때문에 작업을 수행했습니다. 하나의 활동 (MyActivity)과 서로를 대체하는 단편이 거의 모든 가정합니다 (한 번에 하나만 표시됨).
MyActivity에서 다음 리스너를 추가하십시오.
getSupportFragmentManager().addOnBackStackChangedListener(getListener());
(보시다시피 환경 패키지를 사용하고 있습니다).
getListener 구현 :
private OnBackStackChangedListener getListener()
{
OnBackStackChangedListener result = new OnBackStackChangedListener()
{
public void onBackStackChanged()
{
FragmentManager manager = getSupportFragmentManager();
if (manager != null)
{
MyFragment currFrag = (MyFragment) manager.findFragmentById(R.id.fragmentItem);
currFrag.onFragmentResume();
}
}
};
return result;
}
MyFragment.onFragmentResume()
"뒤로"를 호출 한 후 호출됩니다. 하지만 몇 가지주의 사항 :
- 모든 트랜잭션을 백 스택에 추가하고 가정합니다 (사용
FragmentTransaction.addToBackStack()
). - 스택이 변경 될 때마다 활성화 (애니메이션과 같은 백 스택에 다른 스택에 항목을 포함) 동일한 조각 인스턴스에 대해 여러 호출을받을 수 있습니다.
제안 된 솔루션을 약간 변경했습니다. 나를 위해 더 잘 작동합니다.
private OnBackStackChangedListener getListener() {
OnBackStackChangedListener result = new OnBackStackChangedListener() {
public void onBackStackChanged() {
FragmentManager manager = getSupportFragmentManager();
if (manager != null) {
int backStackEntryCount = manager.getBackStackEntryCount();
if (backStackEntryCount == 0) {
finish();
}
Fragment fragment = manager.getFragments()
.get(backStackEntryCount - 1);
fragment.onResume();
}
}
};
return result;
}
후 popStackBack()
다음과 같은 콜백을 사용할 수 있습니다 : onHiddenChanged(boolean hidden)
당신의 조각 내
Android 개발자의 다음 섹션에서는 활동 에 대해 설명합니다 . 한 줄을 인용 비용 :
프래그먼트 내부에 서비스 인터페이스를 정의하고 호스트 활동이이를 구현하도록 요구하는 것입니다. 활동이 인터페이스를 통해 수신하면 필요에 따라 레이아웃의 다른 조각과 정보를 공유 할 수 있습니다.
편집 : 조각에는 onStart(...)
조각이 사용자에게 표시 될 때 호출되는 것이 있습니다. 마 onResume(...)
가시 더 활발하게 실행될 때. 이것들은 대응 활동 물과 연결되어 있습니다. 요컨대 : 사용onResume()
내 활동 onCreate ()
getSupportFragmentManager().addOnBackStackChangedListener(getListener());
이 메서드를 사용하여 특정 Fragment를 실행하고 onResume ()을 호출합니다.
private FragmentManager.OnBackStackChangedListener getListener()
{
FragmentManager.OnBackStackChangedListener result = new FragmentManager.OnBackStackChangedListener()
{
public void onBackStackChanged()
{
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (currentFragment instanceof YOURFRAGMENT) {
currentFragment.onResume();
}
}
};
return result;
}
약간 개선되어 솔루션에 포함되었습니다.
명심할 사항. FragmentManager는 싱글 톤이 기능 내의 Fragment 만 관리하는 모든 활동에서 새로운 것이됩니다. 또한 지금까지이 솔루션은 조각의 가시성을 제어하는 데 도움이되는 setUserVisibleHint () 메서드를 호출하는 ViewPager를 고려하지 않습니다.
이 문제를 처리 할 때 다음 클래스를 자유롭게 사용하십시오 (Dagger2 사용). 활동 요청 :
//inject FragmentBackstackStateManager instance to myFragmentBackstackStateManager
FragmentManager fragmentManager = getSupportFragmentManager();
myFragmentBackstackStateManager.apply(fragmentManager);
FragmentBackstackStateManager.java :
@Singleton
public class FragmentBackstackStateManager {
private FragmentManager fragmentManager;
@Inject
public FragmentBackstackStateManager() {
}
private BackstackCallback backstackCallbackImpl = new BackstackCallback() {
@Override
public void onFragmentPushed(Fragment parentFragment) {
parentFragment.onPause();
}
@Override
public void onFragmentPopped(Fragment parentFragment) {
parentFragment.onResume();
}
};
public FragmentBackstackChangeListenerImpl getListener() {
return new FragmentBackstackChangeListenerImpl(fragmentManager, backstackCallbackImpl);
}
public void apply(FragmentManager fragmentManager) {
this.fragmentManager = fragmentManager;
fragmentManager.addOnBackStackChangedListener(getListener());
}
}
FragmentBackstackChangeListenerImpl.java :
public class FragmentBackstackChangeListenerImpl implements FragmentManager.OnBackStackChangedListener {
private int lastBackStackEntryCount = 0;
private final FragmentManager fragmentManager;
private final BackstackCallback backstackChangeListener;
public FragmentBackstackChangeListenerImpl(FragmentManager fragmentManager, BackstackCallback backstackChangeListener) {
this.fragmentManager = fragmentManager;
this.backstackChangeListener = backstackChangeListener;
lastBackStackEntryCount = fragmentManager.getBackStackEntryCount();
}
private boolean wasPushed(int backStackEntryCount) {
return lastBackStackEntryCount < backStackEntryCount;
}
private boolean wasPopped(int backStackEntryCount) {
return lastBackStackEntryCount > backStackEntryCount;
}
private boolean haveFragments() {
List<Fragment> fragmentList = fragmentManager.getFragments();
return fragmentList != null && !fragmentList.isEmpty();
}
/**
* If we push a fragment to backstack then parent would be the one before => size - 2
* If we pop a fragment from backstack logically it should be the last fragment in the list, but in Android popping a fragment just makes list entry null keeping list size intact, thus it's also size - 2
*
* @return fragment that is parent to the one that is pushed to or popped from back stack
*/
private Fragment getParentFragment() {
List<Fragment> fragmentList = fragmentManager.getFragments();
return fragmentList.get(Math.max(0, fragmentList.size() - 2));
}
@Override
public void onBackStackChanged() {
int currentBackStackEntryCount = fragmentManager.getBackStackEntryCount();
if (haveFragments()) {
Fragment parentFragment = getParentFragment();
//will be null if was just popped and was last in the stack
if (parentFragment != null) {
if (wasPushed(currentBackStackEntryCount)) {
backstackChangeListener.onFragmentPushed(parentFragment);
} else if (wasPopped(currentBackStackEntryCount)) {
backstackChangeListener.onFragmentPopped(parentFragment);
}
}
}
lastBackStackEntryCount = currentBackStackEntryCount;
}
}
BackstackCallback.java :
public interface BackstackCallback {
void onFragmentPushed(Fragment parentFragment);
void onFragmentPopped(Fragment parentFragment);
}
조각이 백 스택에 배치되면 Android는 하나의 뷰를 파괴합니다. 조각 인스턴스 자체는 죽지 재료입니다. 시작하는 간단한 방법은 onViewCreated 이벤트를 수신하는 것입니다. 여기에 "onResume ()"로직을 넣습니다.
boolean fragmentAlreadyLoaded = false;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState == null && !fragmentAlreadyLoaded) {
fragmentAlreadyLoaded = true;
// Code placed here will be executed once
}
//Code placed here will be executed even when the fragment comes from backstack
}
이것은 조각이 활동에 첨부되어 있으면 onResume ()을 호출 할 수있는 정답입니다. 또는 onAttach 및 onDetach를 사용할 수 있습니다.
조각에 대한 onResume ()이 잘 작동합니다 ...
public class listBook extends Fragment {
private String listbook_last_subtitle;
...
@Override
public void onCreate(Bundle savedInstanceState) {
String thisFragSubtitle = (String) getActivity().getActionBar().getSubtitle();
listbook_last_subtitle = thisFragSubtitle;
}
...
@Override
public void onResume(){
super.onResume();
getActivity().getActionBar().setSubtitle(listbook_last_subtitle);
}
...
public abstract class RootFragment extends Fragment implements OnBackPressListener {
@Override
public boolean onBackPressed() {
return new BackPressImpl(this).onBackPressed();
}
public abstract void OnRefreshUI();
}
public class BackPressImpl implements OnBackPressListener {
private Fragment parentFragment;
public BackPressImpl(Fragment parentFragment) {
this.parentFragment = parentFragment;
}
@Override
public boolean onBackPressed() {
((RootFragment) parentFragment).OnRefreshUI();
}
}
효과를보기 위해 RootFragment에서 Frament를 마지막으로 확장합니다.
내 해결 방법은 새 제목으로 설정하기 전에 조각에서 작업 표시 줄의 현재 제목을 가져 오는 것입니다. 이렇게하면 조각이 터지면 해당 제목으로 다시 변경할 수 있습니다.
@Override
public void onResume() {
super.onResume();
// Get/Backup current title
mTitle = ((ActionBarActivity) getActivity()).getSupportActionBar()
.getTitle();
// Set new title
((ActionBarActivity) getActivity()).getSupportActionBar()
.setTitle(R.string.this_fragment_title);
}
@Override
public void onDestroy() {
// Set title back
((ActionBarActivity) getActivity()).getSupportActionBar()
.setTitle(mTitle);
super.onDestroy();
}
FragmentTags
모든 조각 클래스를 정의하기 위해 열거 형 을 사용했습니다.
TAG_FOR_FRAGMENT_A(A.class),
TAG_FOR_FRAGMENT_B(B.class),
TAG_FOR_FRAGMENT_C(C.class)
FragmentTags.TAG_FOR_FRAGMENT_A.name()
조각 태그로 전달합니다 .
그리고 지금
@Override
public void onBackPressed(){
FragmentManager fragmentManager = getFragmentManager();
Fragment current
= fragmentManager.findFragmentById(R.id.fragment_container);
FragmentTags fragmentTag = FragmentTags.valueOf(current.getTag());
switch(fragmentTag){
case TAG_FOR_FRAGMENT_A:
finish();
break;
case TAG_FOR_FRAGMENT_B:
fragmentManager.popBackStack();
break;
case default:
break;
}
참고 URL : https://stackoverflow.com/questions/6503189/fragments-onresume-from-back-stack
'IT' 카테고리의 다른 글
정적 제네릭 메서드 호출 (0) | 2020.08.30 |
---|---|
전체 커밋이 아닌 하나의 파일에 변경 사항을 선택하는 방법 (0) | 2020.08.30 |
여러 생성 기능을위한 JavaScript 패턴 (0) | 2020.08.30 |
gulp.src가 파일에 대한 전체 경로 배열을 전달하는 것을 좋아하지 않는 이유는 무엇입니까? (0) | 2020.08.30 |
식에 대한 Angular lazy 일회성 바인딩 (0) | 2020.08.30 |