1

I've been trying to use Fragments as my RecyclerView children to no avail.

What I have I'm trying to do is load some ArrayList of custom POJO classes from my Firebase Database and each of those items has content to be displayed as the header and the main content.

For that I have created a Foldable layout where the user first sees the header layout and on clicking the desired child in the layout,they are presented with the main content.

The Header layout is a simple ConstraintLayout so no problem in binding data to views. But my Content layout is a ViewPager coupled with TabLayout to host three Fragments whose data comes from the ArrayList fetched from Firebase.

My problem comes in where only the first child's Fragments show data in the onClick event but the rest don't.

This is my RecyclerView Adapter:

public class OrdersAdapter extends RecyclerView.Adapter<OrdersAdapter.viewHolder> {

public static boolean canScroll;
public static String image;
public static String message;
private static boolean isUser;
private static int scrollTo;
private static List<Order> beanOrders;
private FragmentManager fragmentManager;

public OrdersAdapter(List<Order> beanOrders, FragmentManager fragmentManager) {
    OrdersAdapter.beanOrders = beanOrders;
    this.fragmentManager = fragmentManager;
}

@NonNull
@Override
public viewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new viewHolder(new FoldableLayout(parent.getContext()));
}

@Override
public void onBindViewHolder(@NonNull final viewHolder holder, int i) {
    ArrayList<String> location = beanOrders.get(i).getLocation();
    String county = location.get(0);
    String consti = location.get(1);
    String ward = location.get(2);
    String estate = location.get(3);
    String apartm = location.get(4);

    if (beanOrders.get(i).isTaken()) {
        holder.flHolder.setBackground(holder.itemView.getContext().getResources().getDrawable(R.drawable.vector_free));
    } else if (beanOrders.get(i).isDelivered()) {
        holder.flHolder.setBackground(holder.itemView.getContext().getResources().getDrawable(R.drawable.vector_delid));
    }

    holder.tvWorth.setText(String.format("Ksh %s", beanOrders.get(i).getsWorth()));
    holder.tvNumber.setText(beanOrders.get(i).getsPhone());
    holder.tvUserName.setText(beanOrders.get(i).getsName());
    holder.tvCouConWard.setText(String.format("%s , %s , %s", county, consti, ward));
    holder.tvEstApart.setText(String.format("%s , %s", estate, apartm));
}

@Override
public int getItemCount() {
    return (null != beanOrders ? beanOrders.size() : 0);
}

private void setUpData(viewHolder holder, String image, String message) {
    setUpViewPager(holder.vpAdmin, image, message, fragmentManager);
    holder.tbAdmin.setupWithViewPager(holder.vpAdmin);
    holder.vpAdmin.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {

        }

        @Override
        public void onPageSelected(int i) {
            isUser = i == 2;
            if (i == 2) {
                holder.fabClose.setImageResource(R.drawable.vector_eraser);
            } else holder.fabClose.setImageResource(R.drawable.vector_fold);
        }

        @Override
        public void onPageScrollStateChanged(int i) {

        }
    });
}

private void setUpViewPager(HViewPager viewPager, String image, String message, FragmentManager fragmentManager) {
    FragmentsAdapter fragmentsAdapter = new FragmentsAdapter(fragmentManager);

    Image fragmentImage = Image.newInstance(image);
    Message fragmentMessage = Message.newInstance(message);

    fragmentsAdapter.addFragment(new Image(), "Image");
    fragmentsAdapter.addFragment(new Message(), "Confirmation");
    fragmentsAdapter.addFragment(new Delivery(), "Delivery");

    viewPager.setAdapter(fragmentsAdapter);
    viewPager.setPagingEnabled(false);
}

class viewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

    FoldableLayout flAdmin;
    @BindView(R.id.tbAdmin)
    TabLayout tbAdmin;
    @BindView(R.id.vpAdmin)
    HViewPager vpAdmin;
    @BindView(R.id.fabClose)
    FloatingActionButton fabClose;
    @BindView(R.id.tvUserName)
    AppCompatTextView tvUserName;
    @BindView(R.id.tvNumber)
    AppCompatTextView tvNumber;
    @BindView(R.id.tvWorth)
    AppCompatTextView tvWorth;
    @BindView(R.id.tvCouConWard)
    AppCompatTextView tvCouConWard;
    @BindView(R.id.tvEstApart)
    AppCompatTextView tvEstApart;
    @BindView(R.id.tvLoyalty)
    AppCompatTextView tvLoyalty;
    @BindView(R.id.tvPoints)
    AppCompatTextView tvPoints;
    @BindView(R.id.flHolder)
    FrameLayout flHolder;

    viewHolder(FoldableLayout foldableLayout) {
        super(foldableLayout);
        flAdmin = foldableLayout;
        foldableLayout.setupViews(R.layout.layout_c_header, R.layout.layout_c_content, R.dimen.cover_height, itemView.getContext());
        ButterKnife.bind(this, foldableLayout);

        vpAdmin.setPagingEnabled(false);

        canScroll = true;

        fabClose.setOnClickListener(this);

        flAdmin.setOnClickListener((View v) -> {
            image = beanOrders.get(getLayoutPosition()).getsImage();
            message = beanOrders.get(getLayoutPosition()).getsMessage();

            setUpData(this, image, message);
            tbAdmin.setupWithViewPager(vpAdmin);

            //Toast.makeText(itemView.getContext(), beanOrders.get(getLayoutPosition()).getsMessage(), Toast.LENGTH_SHORT).show();
            new Handler().postDelayed(() -> canScroll = false, 1000);

            Intent intent = new Intent(ConstHelper.START_SCROLL);
            intent.putExtra(ConstHelper.SMOOTH_SCROLL, true);
            intent.putExtra(ConstHelper.SCROLL_TO, getLayoutPosition());
            LocalBroadcastManager.getInstance(itemView.getContext()).sendBroadcast(intent);

            if (flAdmin.isFolded()) {
                flAdmin.unfoldWithAnimation();
            } else {
                flAdmin.foldWithAnimation();
            }
        });

        flAdmin.setOnLongClickListener(view -> {
            canScroll = true;
            return true;
        });

    }

    @Override
    public void onClick(View view) {
        canScroll = true;
        if (isUser) {
            canScroll = false;
            Intent intent = new Intent(ConstHelper.SIGNATURE_CALL);
            intent.putExtra(ConstHelper.CLEAR_CUSTOMER, true);
            LocalBroadcastManager.getInstance(viewHolder.this.itemView.getContext()).sendBroadcast(intent);
        } else {
            if (!flAdmin.isFolded()) {
                flAdmin.foldWithAnimation();
            }
        }
    }

    @Override
    public boolean onLongClick(View view) {
        //TODO send report that order has been received

        return true;
    }
}}

The fragments are simple and two follow this pattern:

public class Message extends Fragment {
@BindView(R.id.tvConfirmation)
AppCompatTextView tvConfirmation;
Unbinder unbinder;

public Message() {
}

public static Message newInstance(String message) {
    Bundle bundle = new Bundle();
    bundle.putString("Message", message);

    Message fragmentMessage = new Message();
    fragmentMessage.setArguments(bundle);

    return fragmentMessage;
}

private void readBundle(Bundle bundle) {
    if (bundle != null) {
        //message = bundle.getString("Message");
    }
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.layout_f_message, container, false);

    unbinder = ButterKnife.bind(this, view);
    return view;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    tvConfirmation.setText(OrdersAdapter.message);

    Toast.makeText(getActivity(), OrdersAdapter.message, Toast.LENGTH_SHORT).show();
    //readBundle(getArguments());
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
}}

The other one just loads an image and the last is not linked to the data I'm fetching.

What I've tried

  1. Using Bundles to deliver the data to the Fragment.
  2. Switching where I load my Fragments from ViewHolder class to onBindViewHolder method.

The first seems to work from my debugging but still the issue prevails no matter what.

This is an image of the above situation: Image here

Any help would be appreciated.

Kennedy Kambo
  • 372
  • 4
  • 24
  • 1
    Start by removing all the ```static``` qualifiers from the Adapter's variables. After that, seeing what you want to accomplish, I strongly suggest moving away from the complexity of Fragment to simple Views and ViewHolders. Finally make sure you notify the adapter of any changes. – iFanie Nov 28 '18 at 19:34
  • @iFanie thanks for the response but I don't see any other way to accomplish what I want without the Fragments.Also the adapter is notified but via the class from where I have bound it to the RecyclerView – Kennedy Kambo Nov 28 '18 at 19:43
  • As you wish, then remove all static qualifiers because they should not be there. You want every adapter instance to have it's own set of data and flags. – iFanie Nov 28 '18 at 20:00
  • **[This](https://stackoverflow.com/questions/49383687/how-can-i-retrieve-data-from-firebase-to-my-adapter/49384849)** is a recommended way in which you can retrieve data from a Firebase Realtime database and display it in a `RecyclerView` using `FirebaseRecyclerAdapter`. – Alex Mamo Nov 29 '18 at 12:33
  • Hi @AlexMamo getting and displaying the data is not an issue.But thanks for the suggestion.My problem is using Fragments as children in my Recyclerview – Kennedy Kambo Nov 30 '18 at 11:31
  • @iFanie thanks for the suggestion I actually made it work by switching the view to simpler ones.Maybe you can add this as an answer so I can accept it. – Kennedy Kambo Dec 02 '18 at 20:15
  • @The-Kamble i did, thanks for this. Did you also remove the static variables? – iFanie Dec 02 '18 at 20:20
  • No the static variables are mandatory.I know it is not a good design pattern but for now itll do – Kennedy Kambo Dec 02 '18 at 20:26

1 Answers1

1

Start by removing all the static qualifiers from the Adapter's variables. After that, seeing what you want to accomplish, I strongly suggest moving away from the complexity of Fragment to simple Views and ViewHolders. Finally, make sure you notify the adapter of any changes.

Alireza Noorali
  • 3,129
  • 2
  • 33
  • 80
iFanie
  • 916
  • 8
  • 10