Правильно вызывать функцию на вкладке фрагмента из родительского фрагмента с помощью FragmentPagerAdapter

У меня есть вкладки, созданные с помощью FragmentPagerAdapter:

public class SectionsPagerAdapter extends FragmentPagerAdapter {
static final int PAGE_COUNT = 2;

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

@Override
public Fragment getItem(int index) {
    switch (index) {
    case 0:
        return new SessionDetails();
    case 1:
        return new SessionScoreTable();
    }
    return null;
}

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

Мне нужно обновить одну вкладку, нажав кнопки на другой.

Родитель FragmentActivity имеет:

fragSessionDetails = (SessionDetails) mSectionsPagerAdapter.getItem(0);

и имеет function:

public void setSessionCompleted(){
    fragSessionDetails.processSessionCompleted();
}

который вызывается из другой вкладки (SessionScoreTable).

Вкладка SessionDetails имеет функцию:

    public void processSessionCompleted(){
    Log.d(TAG,"processSessionCompleted" );
        bSave.setEnabled(false);
        }

bСохранить — кнопка.

В журнале у меня есть NullPointerException в строке - bSave.setEnabled(false):

06-30 16:20:45.414: D/STS_SessionDetails(15876): processSessionCompleted 06-30 16:20:45.414: D/AndroidRuntime(15876): завершение работы виртуальной машины 06-30 16:20:45.414: W/dalvikvm(15876 ): threadid=1: поток завершается с необработанным исключением (group=0x41b62d88) 06-30 16:20:45.414: E/AndroidRuntime(15876): Exception 06-30 16:20:45.414: E/AndroidRuntime(15876): FATAL ИСКЛЮЧЕНИЕ: main 06-30 16:20:45.414: E/AndroidRuntime(15876): Процесс: com.vvv.vvvvvvvvvvvvv, PID: 15876 06-30 16:20:45.414: E/AndroidRuntime(15876): java.lang. NullPointerException 06-30 16:20:45.414: E/AndroidRuntime(15876): в com.vvv.vvvvvvvvvvvvv.SessionDetails.processSessionCompleted(SessionDetails.java:237) 06-30 16:20:45.414: E/AndroidRuntime(15876): в com.vvv.vvvvvvvvvvvvv.Session.setSessionCompleted(Session.java:151)

Похоже, я что-то потерял, но понятия не имею, что. Любая помощь, пожалуйста.


person Idol    schedule 30.06.2015    source источник
comment
попробуйте использовать FragmentStateAdapter вместо FragmentPagerAdapter   -  person AndroidManifester    schedule 01.07.2015


Ответы (2)


Линия

fragSessionDetails = (SessionDetails) mSectionsPagerAdapter.getItem(0);

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

public void setSessionCompleted(){
    ((SessionDetails) mSectionsPagerAdapter.getItem(0)).processSessionCompleted();
}
person yshahak    schedule 30.06.2015
comment
почему это плохо? Если существует множество функций, использующих фрагмент, лучше создать его один раз. Или я не считаю с/у? - person Idol; 30.06.2015
comment
Во-первых, это плохо, потому что FragmentAapter может в каком-то случае заменить фрагмент, и ссылка будет неправильной. Во-вторых, вы получили нуль, вероятно, потому, что вы вызвали (SessionDetails) mSectionsPagerAdapter.getItem(0) до того, как адаптер фактически раздует макет внутри ViewPager. - person yshahak; 30.06.2015
comment
Если мой ответ поможет вам, я признателен, если вы примете его. - person yshahak; 30.06.2015
comment
Если бы это было так, у меня нет строки D/STS_SessionDetails(15876): processSessionCompleted в журнале. Спасибо, я пробовал, но это не решило проблему. - person Idol; 01.07.2015

Наконец, у меня есть решение.

public class SectionsPagerAdapter extends FragmentPagerAdapter {
static final int PAGE_COUNT = 2;
private SessionDetails fragSessionDetails;
private SessionScoreTable fragSessionScoreTable;

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

@Override
public Fragment getItem(int index) {
    switch (index) {
    case 0:
        return new SessionDetails();
    case 1:
        return new SessionScoreTable();
    return null;
}

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

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
    // save the appropriate reference depending on position
    switch (position) {
        case 0:
            fragSessionDetails = (SessionDetails) createdFragment;
            break;
        case 1:
            fragSessionScoreTable = (SessionScoreTable) createdFragment;
            break;
    }
    return createdFragment;
}

public SessionDetails getFragSessionDetails(){
    return fragSessionDetails;
}

public SessionScoreTable getFragSessionScoreTable(){
    return fragSessionScoreTable;
}}

а также

    public void setSessionCompleted(){
    SessionDetails fragSessionDetails = mSectionsPagerAdapter.getFragSessionDetails();
    if (fragSessionDetails != null) {
        Log.d(TAG, "fragSessionDetails");
        fragSessionDetails.processSessionCompleted();
    }
}

Идея из https://stackoverflow.com/a/29287415/2881525

person Idol    schedule 30.06.2015