Обновление макета фрагмента в ViewPager

У меня есть активность, которая использует ViewPager с 4 фрагментами. Я использую FragmentPagerAdapter для заполнения страниц.

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new FragmentA()
            case 1:
                return new ProfileFragment();
            case 2:
                return new FragmentC();
            case 3:
                return new FragmentD();
        }
        return null;
    }

    @Override
    public int getCount() {
        return 4;
    }
}

Один из этих фрагментов показывает детали пользователя (ProfileFragment в приведенном выше коде) по следующим критериям:

  • Если пользователь не вошел в систему, показать макет входа
  • Если пользователь вошел в систему, показать макет профиля

Следовательно, когда пользователь открывает приложение в первый раз, будет отображаться макет входа в систему, а когда пользователь входит в систему, необходимо обновить фрагмент, чтобы показать макет профиля.

Подход, который я планировал использовать, состоял в том, что когда пользователь входит в систему, перейдите к FragmentA и уничтожьте существующий ProfileFragment. Метод onCreateView в ProfileFragment обрабатывает отображаемый макет в зависимости от состояния входа в систему.

public class ProfileFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        int layout = userLoggedIn() ? R.layout.fragment_user_login : R.layout.fragment_user_profile;
        return inflater.inflate(layout, container, false);
    }

    // Handler for login
    public void loginUser() {
        ((MyActivity) getActivity()).loginUser();
    }
}

public class MyActivity extends AppCompatActivity {

    private SectionsPagerAdapter mSectionsPagerAdapter;

    public void loginUser() {
        // 1. Set login details as needed
        ...
        // 2. Navigate to FragmentA
        ...
        // 3. Destroy ProfileFragment
        mSectionsPagerAdapter.destroyItem(container, 1, object); // How to get `object` here?
    }
}

У меня есть два вопроса по этому поводу:

  1. Метод destroyItem принимает Object object вернулся из instantiateItem, Как получить это значение при уничтожении? Нужно ли перезаписывать instantiateItem и поддерживать Map<Integer, Object> с позиции на объект?
  2. Есть ли лучший способ обновить вид фрагмента, не разрушая фрагмент полностью?

1 ответ

Решение

Я сделал что-то подобное, прежде чем использовать FragmentStatePagerAdapter, вы можете вызвать notifyDataSetChanged. GetItemPosition вызывается для каждого существующего фрагмента, если вы вызываете super.getItemPosition, оно возвращает POSITION_UNCHANGED, когда означает, что фрагмент не изменился, если вы вернетесь, POSITION_NONE приведет к тому, что фрагмент в этой позиции будет перезагружается. Вы можете использовать это в методе getItem для предоставления фрагмента профиля.

В этом решении вам просто нужно вызвать setLoggedIn

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
boolean isLoggedIn = false;
boolean userHasJustLoggedIn = false;

public SectionsPagerAdapter(FragmentManager fm) {
    super(fm);
}

public void setIsLoggedIn() {
    isLoggedIn = true;
    userHasJustLoggedIn = true;
    notifyDataSetChanged();
}

@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            return new FragmentA()
        case 1:

            if (isLoggedIn) {
                return new ProfileFragment();
            } else {
                return new LoginFragment();
            }
        case 2:
            return new FragmentC();
        case 3:
            return new FragmentD();
    }
    return null;
}

@Override
public int getItemPosition(Object object) {
    Fragment fragment = (Fragment) object;
    if (fragment instanceof LoginFragment && userHasJustLoggedIn) {
        userHasJustLoggedIn = false;
        return POSITION_NONE;
    }

    return super.getItemPosition(object);
}

@Override
public int getCount() {
    return 4;
}

}

Другие вопросы по тегам