替换视图内部的碎片分页器空指针异常

时间:2016-06-04 07:11:12

标签: android android-viewpager android-tablayout

我的目标是替换viewpager中的Fragment。我得到了相同的Replace one fragment with other

的匹配解决方案

以下是我在上面链接中使用的代码

 public interface SecondPageFragmentListener {
     void onSwitchToNextFragment();
}

我已经在我的ViewPager Adapter中实现了上面的接口。我只是粘贴了适用于适配器的完整代码,因此很容易理解每​​个人

public class TabPagerAdapter extends FragmentPagerAdapter{

    private final Resources resources;
    private Context mContext;
    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
    Fragment result = null;
    FirstPageListener listener = new FirstPageListener();
    public TabPagerAdapter(final Resources resources, FragmentManager  fm,Context mContext) {
        super(fm);
        this.mContext = mContext;
        this.resources = resources;
    }


    public void updateData(){
        notifyDataSetChanged();
    }


    @Override
    public Fragment getItem(int position) {

        switch (position) {
            case 0:
                // First Fragment of First Tab
                result = new Position();
                break;
            case 1:
                // First Fragment of Second Tab
                result =  new Alerts();
                break;
            case 2:
                // First Fragment of Third Tab
                result = new Reports();
                break;
            default:
                result = null;
                break;
        }

        return result;
    }

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

    @Override
    public CharSequence getPageTitle(final int position) {
         switch (position) {
            case 0:
                return resources.getString(R.string.tab_position_title);
            case 1:
                return resources.getString(R.string.tab_alert_title);
            case 2:
                return resources.getString(R.string.tab_reports_title);
            default:
                return null;
            }
    }

    @Override
    public int getItemPosition(Object object)
    {
        if (object instanceof Alerts &&
                result instanceof CaptureIncident) {
            return POSITION_NONE;
        }
        if (object instanceof CaptureIncident &&
                result instanceof Alerts) {
            return POSITION_NONE;
        }
        return POSITION_UNCHANGED;
    }



    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment)   super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }


    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }



    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }
    private final class FirstPageListener implements
        SecondPageFragmentListener {
        public void onSwitchToNextFragment() {

((AppCompatActivity)mContext).getSupportFragmentManager().beginTransaction().remove(result)
                .commit();
            if (result instanceof Alerts){
                result =   CaptureIncident.newInstance("","",listener);
            }else{ // Instance of NextFragment
                result =  Alerts.newInstance("","",listener);
            }
            notifyDataSetChanged();
         }
     }


 }

我刚刚创建了一个Inner类,并实现了我在链接中提到的SecondPageFragmentListener接口。

现在我在我的Alert Fragment中启用了界面

static SecondPageFragmentListener secondPageListener;
    public static Alerts newInstance(String param1, String param2,SecondPageFragmentListener listener) {
        Alerts fragment = new Alerts();
        secondPageListener = listener;
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

现在我在按钮上点击

调用接口方法
secondPageListener.onSwitchToNextFragment();

以下是My Fragment Code

public class Alerts extends RootFragment{

    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";


    private String mParam1;
    private String mParam2;
    private RecyclerView gridview;
    private GridAdapter gridAdapter;
    private GridLayoutManager gridLayoutManager;

    private OnFragmentInteractionListener mListener;
     public static SecondPageFragmentListener secondPageListener;
    public Alerts() {
        // Required empty public constructor
    }
    @SuppressLint("ValidFragment")
    public Alerts(SecondPageFragmentListener listener){
        secondPageListener = listener;
    }


    public static Alerts newInstance(String param1, String param2,SecondPageFragmentListener listener) {
        Alerts fragment = new Alerts();
        secondPageListener = listener;
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_alerts, container,  false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         initUiView();
         RecyclerListener();
}

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
         }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
     }

     public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
     }

     private void initUiView() {
         gridview =  (RecyclerView)getActivity().findViewById(R.id.gridview);
         gridview.setHasFixedSize(true);
         gridview.setLayoutManager(new GridLayoutManager(getActivity(), 3));

        //list Population
         List<ItemObject> rowListItem = getAllItemList();
         gridAdapter = new GridAdapter(getActivity(),rowListItem);
         gridview.setAdapter(gridAdapter);
         gridAdapter.notifyDataSetChanged();
     }

      private List<ItemObject> getAllItemList(){

          List<ItemObject> allItems = new ArrayList<ItemObject>();
         allItems.add(new ItemObject("altercation","0,50 miles - 10 min ago", R.drawable.altercation));
         allItems.add(new ItemObject("offence","0,25 miles - 45 min ago", R.drawable.offence));
          allItems.add(new ItemObject("harassment","0,60 miles - 1h ago", R.drawable.harassment));
          allItems.add(new ItemObject("doubt","0,5 miles - 48 min ago", R.drawable.doubt));
          allItems.add(new ItemObject("incident","0,50 miles - 30 min ago", R.drawable.incident));

         return allItems;
     }

     private void RecyclerListener(){
    gridview.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), gridview, new ItemClickListener(){
             @Override
             public void onClick(View view, int position) {
                 Alerts.secondPageListener.onSwitchToNextFragment();
      }

             @Override
             public void onLongClick(View view, int position) {

             }
         }));
     }
}

但是它显示了错误

  java.lang.NullPointerException
                                                                   at   
com.oxilo.mrsafer.fragement.Alerts$1.onClick(Alerts.java:173)

错误表示secondpagelitener为空。

请帮我解决这个问题。

另请参阅以下链接 Replace one fragment with other

他在Fragment中实现了与他已经实现的相同的接口 视图寻呼机适配器中的接口。所以他为什么也要在片段中实施。从我的理解错了,但如果我错了请纠正我。

2 个答案:

答案 0 :(得分:0)

您正在调用此代码

public void onSwitchToNextFragment() {

    ((AppCompatActivity)mContext).getSupportFragmentManager().beginTransaction().remove(result).commit();
    if (result instanceof Alerts){
       result =   CaptureIncident.newInstance("","",listener);
    } else{ // Instance of NextFragment
       result =  Alerts.newInstance("","",listener);
    }
    notifyDataSetChanged();
}

从此处创建的对象:

case 1:
    // First Fragment of Second Tab
    result =  new Alerts();
    break;

所以secondPageListener尚未初始化。您可以尝试将代码更改为:

 @Override
 public Fragment getItem(int position) {

    switch (position) {
        case 0:
            // First Fragment of First Tab
            result = new Position();
            break;
        case 1:
            // First Fragment of Second Tab
            result =  Alerts.newInstance("","",listener); // This line is important
            break;
        case 2:
            // First Fragment of Third Tab
            result = new Reports();
            break;
        default:
            result = null;
            break;
    }

    return result;
}

修改

如果它是静态的那么你可以试试这个:

 @Override
 public Fragment getItem(int position) {

    switch (position) {
        case 0:
            // First Fragment of First Tab
            result = new Position();
            break;
        case 1:
            // First Fragment of Second Tab
            result =  Alerts.newInstance("","",listener); // This line is important
            Alerts.secondPageListener = listener;
            break;
        case 2:
            // First Fragment of Third Tab
            result = new Reports();
            break;
        default:
            result = null;
            break;
    }

    return result;
}

还要确保在onClick

中像这样调用它
Alerts.secondPageListener.onSwitchToNextFragment();

答案 1 :(得分:0)

你可以试试这个。对于tab2片段创建xml文件,如下所示:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:id="@+id/main"> <!-- this line is the most important part-->
   <!-- your other layout s or views go here-->
</FrameLayout>

或者只是在你的frag xml中将id设置为你的topest布局,并在java代码中将它用作容器id。

然后在您的片段代码中,您尝试调用接口切换片段,只需执行此操作:

 getChildFragmentManager().beginTransaction().replace(R.id.main, destfragment).addToBackStack("youtag").commit();