0

Currently, I am trying to create a nested view pager using a fragment, how can I access top parent function to refresh the View?

Let's say I have:

 public class ParentFragment extends Fragment {

    ...{
    ...
    viewPagerAdapter = new ViewPagerParentAdapter(getChildFragmentManager(), listOfItem);
    viewPager.setAdapter(viewPagerAdapter);
    }

public void refreshView(){
    loadData();
}


private class ViewPagerParentAdapter extends FragmentStatePagerAdapter{
    private List<String> tabTitle;
    private List<Item> listOfItem;
    public ViewPagerParentAdapter(FragmentManager fm, @NonNull List<Item> listOfItem) {
        super(fm);

        this.tabTitle = new ArrayList<>();
        this.listOfItem = new ArrayList<>();

        if (listOfItem.size() > 0) {
            this.listOfItem = listOfItem;

            for (Item item : this.listOfItem) {
                tabTitle.add(Item.getCLASSIFICATION());
            }
        }
        notifyDataSetChanged();
    }

    @Override
    public Fragment getItem(int position) {
        return DetailFragment.newInstance(getItemAtPosition(position).getDETAILS());
    }

     public Item getItemAtPosition(int position) {
        return listOfItem != null ? listOfItem.get(position) : null;
    }
}
}

and here my object

public class Item{
    //POJO
    private String CLASSIFICATION;
    private Details details;
}

detail fragment

public class DetailFragment extends Fragment{

...{
    ...
    Details details = getArguments().getParcelable("details");

    viewPagerAdapter = new DetailViewPagerAdapter(getChildFragmentManager(), details);
    viewPagerDetails.setAdapter(viewPagerAdapter);
}

public void refreshParentView(){
    ((ParentFragment) getParentFragment()).refreshView(); //getting Null
}

public class DetailViewPagerAdapter extends FragmentStatePagerAdapter {

    String[] tabTitle = {"Components", "Materials", "Descriptions"};
    Details details;


    public DetailViewPagerAdapter(FragmentManager fm, @NonNull Details details) {
        super(fm);
        this.details = details;
        notifyDataSetChanged();
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return DetailsChildFragment.newInstance(details.getCOMPONENT());
            case 1:
                return DetailsChildFragment.newInstance(details.getMATERIAL());
            case 2:
                return DetailsChildFragment.newInstance(details.getDESC());
        }
        return null;
    }

    @Override
    public int getCount() {
        return tabTitle.length;
    }
}
}

last child fragment

public class DetailsChildFragment extends Fragment implements View.OnClickListener{

...{
...
...

Button buttonRefresh = (Button)getView().findViewById(R.id.button_refresh);
buttonRefresh.setOnClickListener(this);
}

@Override
public void onClick(View view){
    switch(view.getId()){
        case R.id.button_refresh:
            ((DetailFragment)getParentFragment()).refreshParentView();
        break;
    }
}

}

Currently I am getting Null on the detail fragment refreshParentView

Any suggestions? Thanks in advance

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

2 Answers2

1

You could use an interface as a Listener for events happening in the child

public interface Listener{
  void onRefreshButtonClicked();
}

The child fragment needs to have a Listener as a field, and then you could set the Listener when getting an instance of the child fragment.

public class ChildFragment extends Fragment{

private Listener listener;

public void setListener(Listener listener)//setter
...

//now on button click you call the listener
refreshButton.setOnClickListener(new View.OnClickListener(){

    @Override onClick(){
        if(listener!=null){
            listener.onRefreshButtonClicked();
        }
    }
}




public class ParentFragment extends Fragment{
    ...


    ChildFragment child = ChildFragment.getInstance()
    child.setListener(new Listener(){
        @Override
        void onRefreshButtonClicked(){
// implement your logic
        }
    }

An advantage of doing it like this is that you don't need to cast the parent from Fragment to ParentFragment which makes your code re-usable should you ever need to

vlatkozelka
  • 909
  • 1
  • 12
  • 27
0

When you add your DetailFragment do it with a tag, so that you can retrieve it's instance when you need it. Example:

getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, detailFragment,"detailFragmentTag").commit();

Now, any time you need to access this fragment, you only need to call

DetailFragment parentFragment = (DetailFragment) getActivity().getSupportFragmentManager().findFragmentByTag("detailFragmentTag");
if(detailFragment != null && detailFragment.isAdded()){ //check if it is not null and it is added to the view so you dont end up in some NPE
    detailFragment.refreshParentView()
Ricardo
  • 9,136
  • 3
  • 29
  • 35
  • thanks for your answer it's correct if access the second parent, but i need to access the top of parent (ParentFragment(this) -> DetailFragment(not this) ->DetailChildFragment), thanks man – Aldi Renaldi Gunawan Jul 17 '17 at 14:59