Ошибка при вызове метода у третьего фрагмента

У меня есть пример программы, как показано ниже, что я упростил. При вызове метода в третьем фрагменте возникает ошибка (ListFragment). Тогда как все в порядке, когда я вызываю метод в другом фрагменте, хотя бы из третьего фрагмента.

Когда я меняюсь ListFragment к первому или второму фрагменту, тогда все в порядке, когда я вызываю метод внутри ListFragment, И фрагмент замены, который я помещаю в третий фрагмент, получает ошибку, когда я вызываю метод для этого.

Понятия не имею, где мои ошибки. Большое спасибо за любой ответ.

Примечание: ошибка означает, что программа закрывается и появляется "Unfortunately, program has stooped."

Вот моя программа:

MainActivity.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

import java.util.Locale;

import id.my.zain.tupperware.fragment.ItemFragment;
import id.my.zain.tupperware.fragment.ListFragment;
import id.my.zain.tupperware.fragment.UserFragment;

public class MainActivity extends FragmentActivity {

    private UserFragment userFragment;
    private ItemFragment itemFragment;
    private ListFragment listFragment;

    SectionsPagerAdapter mSectionsPagerAdapter;
    ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        userFragment = new UserFragment();
        itemFragment = new ItemFragment();
        listFragment = new ListFragment();

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);
    }

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

        @Override
        public Fragment getItem(int position) {
            Fragment fragment = new Fragment();

            switch (position) {
                case 0:
                    return fragment = userFragment;
                case 1:
                    return fragment = itemFragment;
                case 2:
                    return fragment = listFragment;
                default:
                    break;
            }
            return fragment;
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();
            switch (position) {
                case 0:
                    return getString(R.string.title_section1).toUpperCase(l);
                case 1:
                    return getString(R.string.title_section2).toUpperCase(l);
                case 2:
                    return getString(R.string.title_section3).toUpperCase(l);
            }
            return null;
        }
    }
}

UserFragment.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import id.my.zain.tupperware.R;
import id.my.zain.tupperware.form.UserForm;

public class UserFragment extends Fragment implements View.OnClickListener{

    private UserForm form;
    private ItemFragment itemFragment;
    private ListFragment listFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_user, container, false);

        form = new UserForm(rootView);

        itemFragment = (ItemFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag("android:switcher:" + R.id.pager + ":1");
        listFragment = (ListFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag("android:switcher:" + R.id.pager + ":2");

        form.getUser_item().setOnClickListener(this);
        form.getUser_list().setOnClickListener(this);

        return rootView;
    }

    public void onClick(View v) {
        if (v == form.getUser_item()) {
            itemFragment.user();
        }

        else if (v == form.getUser_list()) {
            listFragment.user();
        }
    }

    public void item() {
        int a = 1;
    }

    public void list() {
        int a = 1;
    }
}

ItemFragment.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import id.my.zain.tupperware.R;
import id.my.zain.tupperware.form.ItemForm;

public class ItemFragment extends Fragment implements View.OnClickListener {

    private ItemForm form;
    private UserFragment userFragment;
    private ListFragment listFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_item, container, false);

        form = new ItemForm(rootView);

        userFragment = (UserFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag("android:switcher:" + R.id.pager + ":0");
        listFragment = (ListFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag("android:switcher:" + R.id.pager + ":2");

        form.getItem_user().setOnClickListener(this);
        form.getItem_list().setOnClickListener(this);

        return rootView;
    }

    public void onClick(View v) {
        if (v == form.getItem_user()) {
            userFragment.item();
        }

        else if (v == form.getItem_list()) {
            listFragment.item();
        }
    }

    public void user() {
        int a = 1;
    }

    public void list() {
        int a = 1;
    }
}

ListFragment.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import id.my.zain.tupperware.R;
import id.my.zain.tupperware.form.ListForm;

public class ListFragment extends Fragment implements View.OnClickListener {

    private ListForm form;
    private UserFragment userFragment;
    private ItemFragment itemFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_list, container, false);

        form = new ListForm(rootView);

        userFragment = (UserFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag("android:switcher:" + R.id.pager + ":0");
        itemFragment = (ItemFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag("android:switcher:" + R.id.pager + ":1");

        form.getList_user().setOnClickListener(this);
        form.getList_item().setOnClickListener(this);

        return rootView;
    }

    public void onClick(View v) {
        if (v == form.getList_user()) {
            userFragment.list();
        }

        else if (v == form.getList_item()) {
            itemFragment.list();
        }
    }

    public void user() {
        int a = 1;
    }

    public void item() {
        int a = 1;
    }
}

Ошибка Logcat, когда я вызываю метод из UserActivity

11-11 13:21:09.273    2806-2806/id.my.zain.tupperware E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NullPointerException
            at id.my.zain.tupperware.fragment.UserFragment.onClick(UserFragment.java:42)
            at android.view.View.performClick(View.java:4202)
            at android.view.View$PerformClick.run(View.java:17340)
            at android.os.Handler.handleCallback(Handler.java:725)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5039)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)

Ошибка Logcat при вызове метода из ItemActivity

11-11 15:02:03.104    3291-3291/id.my.zain.tupperware E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NullPointerException
            at id.my.zain.tupperware.fragment.ItemFragment.onClick(ItemFragment.java:42)
            at android.view.View.performClick(View.java:4202)
            at android.view.View$PerformClick.run(View.java:17340)
            at android.os.Handler.handleCallback(Handler.java:725)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5039)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)

2 ответа

Решение

ViewPager хранит текущий, правый и, если есть, левый фрагменты. Когда ты в UserFragment у вас есть только UserFragment а также ItemFragment, когда ты в ItemFragment у вас есть все ваши фрагменты. И когда ты в ListFragment у вас есть только ListFragment а также ItemFragment,

У вас есть npe в UserFragment:

UserFragment.onClick(UserFragment.java:42)

Эта часть вашего кода на UserFragment, вызывает ваш нпэ:

public void onClick(View v) {
    if (v == form.getUser_item()) {
        itemFragment.user();
    }

    else if (v == form.getUser_list()) {
        listFragment.user();
       // debug here, you'll see that listFragment is null. thus listFragment.user() throws a npe.
    }
}

Так как listFragment нулевой. Это плохая идея обрабатывать события щелчка фрагмента в другом фрагменте. Попытайтесь поместить своих слушателей щелчка в соответствующие фрагменты.

РЕДАКТИРОВАТЬ:
Решить свой нпэ; примите во внимание мой ответ.
На UserFragment Вы можете иметь ссылку на ItemFragment,
На ItemFragment Вы можете иметь ссылки на оба UserFragment а также ListFragment,
На ListFragment Вы можете иметь ссылку на ItemFragment,
Другие ссылки помогут вам получить npe.

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

РЕДАКТИРОВАТЬ 2: Для вашей реализации ViewPager метод setOffscreenPageLimit может быть решением для вас. Установите более 2 и попробуйте снова.

Это плохой подход, вы не должны вызывать другие методы фрагментов / действий из другого действия или фрагмента. Вы можете использовать шаблон Observer для достижения этой цели.

Но вот обновленный код, он будет работать в вашем случае.

п

ublic void onClick(View v) {
        if (v == form.getItem_user()) {
            if(usreFragment == null)
              {
               userFragment = new UserFragment();
             }
            userFragment.item();
        }

        else if (v == form.getItem_list()) {
             if(listFragment == null)
             {
                listFragment = new ListFragment();
             }            
             listFragment.item();
        }
    }
Другие вопросы по тегам