У меня есть активность, которая использует 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, возвращенный из instantiateItem. Как получить это значение при разрушении? Нужно ли мне перезаписывать instantiateItem и поддерживать Map от позиции к объекту?
  2. Есть ли лучший способ обновить вид фрагмента без его полного уничтожения?

Ответы (1)

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

in this solution you just need to call 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;
}

}

2022 WebDevInsider