developer tip

백 스택에서 최신 조각 가져 오기

optionbox 2020. 8. 26. 07:47
반응형

백 스택에서 최신 조각 가져 오기


백 스택에 최신 조각 인스턴스를 추가하려면 어떻게해야합니까 (조각 태그 및 ID를 모르는 경우)?

FragmentManager fragManager = activity.getSupportFragmentManager();
FragmentTransaction fragTransacion = fragMgr.beginTransaction();

/****After add , replace fragments 
  (some of the fragments are add to backstack , some are not)***/

//HERE, How can I get the latest added fragment from backstack ??

API 레벨 14에서 도입 된 getName()메소드를 사용할 수 있습니다 FragmentManager.BackStackEntry.이 메소드는를 사용하여 백 스택에 Fragment를 추가 할 때 사용한 태그를 반환합니다 addTobackStack(tag).

int index = getActivity().getFragmentManager().getBackStackEntryCount() - 1
FragmentManager.BackStackEntry backEntry = getFragmentManager().getBackStackEntryAt(index);
String tag = backEntry.getName();
Fragment fragment = getFragmentManager().findFragmentByTag(tag);

다음과 같이 백 스택에 조각을 추가했는지 확인해야합니다.

fragmentTransaction.addToBackStack(tag);

FragmentManager.findFragmentById(fragmentsContainerId) 

함수Fragment백 스택의 맨 위로 링크를 반환합니다 . 사용 예 :

    fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            Fragment fr = fragmentManager.findFragmentById(R.id.fragmentsContainer);
            if(fr!=null){
                Log.e("fragment=", fr.getClass().getSimpleName());
            }
        }
    });

나는 이러한 솔루션 중 많은 것을 개인적으로 시도했고 결국이 작동하는 솔루션으로 끝났습니다.

백 스택의 조각 수를 가져 오기 위해 아래에서 여러 번 사용할이 유틸리티 메서드를 추가합니다.

protected int getFragmentCount() {
    return getSupportFragmentManager().getBackStackEntryCount();
}

그런 다음 FragmentTransaction 메소드를 사용하여 프래그먼트를 추가 / 교체 할 때 프래그먼트에 고유 태그를 생성합니다 (예 : 스택의 프래그먼트 수 사용).

getSupportFragmentManager().beginTransaction().add(yourContainerId, yourFragment, Integer.toString(getFragmentCount()));

마지막으로이 방법을 사용하여 백 스택에서 조각을 찾을 수 있습니다.

private Fragment getFragmentAt(int index) {
    return getFragmentCount() > 0 ? getSupportFragmentManager().findFragmentByTag(Integer.toString(index)) : null;
}

따라서 다음을 호출하여 백 스택에서 최상위 조각을 쉽게 가져올 수 있습니다.

protected Fragment getCurrentFragment() {
    return getFragmentAt(getFragmentCount() - 1);
}

도움이 되었기를 바랍니다!


이 도우미 메서드는 스택 상단에서 조각을 가져옵니다.

public Fragment getTopFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String fragmentTag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return getSupportFragmentManager().findFragmentByTag(fragmentTag);
}

fragmentMananger에 조각 목록이 있습니다. 조각을 제거해도 목록 크기가 줄어들지는 않습니다 (조각 항목이 null로 변경됨). 따라서 유효한 솔루션은 다음과 같습니다.

public Fragment getTopFragment() {
 List<Fragment> fragentList = fragmentManager.getFragments();
 Fragment top = null;
  for (int i = fragentList.size() -1; i>=0 ; i--) {
   top = (Fragment) fragentList.get(i);
     if (top != null) {
       return top;
     }
   }
 return top;
}

나는 항상 null을 받기 때문에 deepak goel이 제공하는 대답은 나를 위해 작동하지 않습니다 entry.getName().

내가하는 일은 다음과 같이 조각에 태그를 설정하는 것입니다.

ft.add(R.id.fragment_container, fragmentIn, FRAGMENT_TAG);

ft는 내 조각 트랜잭션이고 FRAGMENT_TAG태그입니다. 그런 다음이 코드를 사용하여 조각을 가져옵니다.

Fragment prev_fragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG);

@roghayeh hosseini (올바른) 답변을 받아 2017 년에 여기있는 사람들을 위해 Kotlin에서 만들었습니다. :)

fun getTopFragment(): Fragment? {
    supportFragmentManager.run {
        return when (backStackEntryCount) {
            0 -> null
            else -> findFragmentByTag(getBackStackEntryAt(backStackEntryCount - 1).name)
        }
    }
}

* 활동 내에서 호출해야합니다.

즐겨 :)


Kotlin

activity.supportFragmentManager.fragments.last()

getBackStackEntryAt () 사용할 수 있습니다 . 활동이 백 스택에 얼마나 많은 항목을 보유하고 있는지 알기 위해 getBackStackEntryCount ()를 사용할 수 있습니다.

int lastFragmentCount = getBackStackEntryCount() - 1;

자신의 백 스택 유지 : myBackStack. 당신이로 Add받는 조각 FragmentManager, 또한 그것을하기 위해 추가 myBackStack. 에서 onBackStackChanged()에서 팝 myBackStack의 길이보다 큰 경우 getBackStackEntryCount.


아래 코드가 저에게 완벽하게 작동하기 때문에 뭔가 더 나은 것으로 보이지만 이미 제공된 답변에서 찾지 못했습니다.

Kotlin :

supportFragmentManager.fragments[supportFragmentManager.fragments.size - 1]

자바:

getSupportFragmentManager().getFragments()
.get(getSupportFragmentManager().getFragments().size() - 1)

Actually there's no latest fragment added to the stack because you can add several or fragments to the stack in a single transaction or just remove fragments without adding a new one.

If you really want to have a stack of fragments and to be able to access a fragment by its index in the stack, you'd better have an abstraction layer over the FragmentManager and its backstack. Here's how you can do it:

public class FragmentStackManager {
  private final FragmentManager fragmentManager;
  private final int containerId;

  private final List<Fragment> fragments = new ArrayList<>();

  public FragmentStackManager(final FragmentManager fragmentManager,
      final int containerId) {
    this.fragmentManager = fragmentManager;
    this.containerId = containerId;
  }

  public Parcelable saveState() {
    final Bundle state = new Bundle(fragments.size());
    for (int i = 0, count = fragments.size(); i < count; ++i) {
      fragmentManager.putFragment(state, Integer.toString(i), fragments.get(i));
    }
    return state;
  }

  public void restoreState(final Parcelable state) {
    if (state instanceof Bundle) {
      final Bundle bundle = (Bundle) state;
      int index = 0;
      while (true) {
        final Fragment fragment =
            fragmentManager.getFragment(bundle, Integer.toString(index));
        if (fragment == null) {
          break;
        }

        fragments.add(fragment);
        index += 1;
      }
    }
  }

  public void replace(final Fragment fragment) {
    fragmentManager.popBackStackImmediate(
        null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    fragmentManager.beginTransaction()
        .replace(containerId, fragment)
        .addToBackStack(null)
        .commit();
    fragmentManager.executePendingTransactions();

    fragments.clear();
    fragments.add(fragment);
  }

  public void push(final Fragment fragment) {
    fragmentManager
        .beginTransaction()
        .replace(containerId, fragment)
        .addToBackStack(null)
        .commit();
    fragmentManager.executePendingTransactions();

    fragments.add(fragment);
  }

  public boolean pop() {
    if (isEmpty()) {
      return false;
    }

    fragmentManager.popBackStackImmediate();

    fragments.remove(fragments.size() - 1);
    return true;
  }

  public boolean isEmpty() {
    return fragments.isEmpty();
  }

  public int size() {
    return fragments.size();
  }

  public Fragment getFragment(final int index) {
    return fragments.get(index);
  }
}

Now instead of adding and removing fragments by calling FragmentManager directly, you should use push(), replace(), and pop() methods of FragmentStackManager. And you will be able to access the topmost fragment by just calling stack.get(stack.size() - 1).

But if you like hacks, I have to other ways of doing similar things. The only thing I have to mention is that these hacks will work only with support fragments.

The first hack is just to get all active fragments added to the fragment manager. If you just replace fragments one by one and pop the from the stack this method will return the topmost fragment:

public class BackStackHelper {
  public static List<Fragment> getTopFragments(
      final FragmentManager fragmentManager) {
    final List<Fragment> fragments = fragmentManager.getFragments();
    final List<Fragment> topFragments = new ArrayList<>();

    for (final Fragment fragment : fragments) {
      if (fragment != null && fragment.isResumed()) {
        topFragments.add(fragment);
      }
    }

    return topFragments;
  }
}

The second approach is event more hacky and allows you to get all fragments added in the last transaction for which addToBackStack has been called:

package android.support.v4.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BackStackHelper {
  public static List<Fragment> getTopFragments(
      final FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() == 0) {
      return Collections.emptyList();
    }

    final List<Fragment> fragments = new ArrayList<>();

    final int count = fragmentManager.getBackStackEntryCount();
    final BackStackRecord record =
        (BackStackRecord) fragmentManager.getBackStackEntryAt(count - 1);
    BackStackRecord.Op op = record.mHead;
    while (op != null) {
      switch (op.cmd) {
        case BackStackRecord.OP_ADD:
        case BackStackRecord.OP_REPLACE:
        case BackStackRecord.OP_SHOW:
        case BackStackRecord.OP_ATTACH:
          fragments.add(op.fragment);
      }
      op = op.next;
    }

    return fragments;
  }
}

Please notice that in this case you have to put this class into android.support.v4.app package.


Or you may just add a tag when adding fragments corresponding to their content and use simple static String field (also you may save it in activity instance bundle in onSaveInstanceState(Bundle) method) to hold last added fragment tag and get this fragment byTag() at any time you need...


The highest (Deepak Goel) answer didn't work well for me. Somehow the tag wasn't added properly.

I ended up just sending the ID of the fragment through the flow (using intents) and retrieving it directly from fragment manager.


If you use addToBackStack(), you can use following code.

List<Fragment> fragments = fragmentManager.getFragments(); activeFragment = fragments.get(fragments.size() - 1);

참고URL : https://stackoverflow.com/questions/9702216/get-the-latest-fragment-in-backstack

반응형