2

I have three classes viz. an Fragment, a RecyclerViewAdapter and a RecyclerViewHolder. They work in the usual way. But now I got a problem, I need to call a method in the ViewHolder from the said Activity.

I was thinking of using callbacks but I tried and it's not working. This is what I have done so far:

The interface

public interface TreeBottomListener {
    enum Status {FAILED, SUCCESS, PRE_REQUEST}
    void onResponse(Status status);
}

The ViewHolder

public class TreeBottomViewHolder extends RecyclerView.ViewHolder implements TreeBottomListener{
    @BindView(R.id.tree_bottom_progress) ProgressBar bottomProgress;
    @BindView(R.id.tree_error_button) Button moreRetryButton;
    private TreeAdapterListener listener;
    private final String TAG = "TreeBottomViewHolder";

    public TreeBottomViewHolder(View itemView, final TreeAdapterListener listener) {
        super(itemView);
        ButterKnife.bind(this, itemView);
        this.listener = listener;
        setUpViews();
    }

    private void setUpViews() {
        bottomProgress.getIndeterminateDrawable().setColorFilter(ContextCompat.getColor
                (itemView.getContext(), R.color.colorAccent), PorterDuff.Mode.SRC_IN);

        moreRetryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setVisibility(View.GONE);
                listener.onLoadMoreClicked();
            }
        });
    }

    @Override
    public void onResponse(Status status) {
        processViews(status);
    }

    private void processViews(Status status) {
    //  This method is never called
        Log.i(TAG, "onResponse: with status " + status);
        if (status == Status.FAILED) {
            bottomProgress.setVisibility(View.GONE);
            moreRetryButton.setVisibility(View.VISIBLE);

        } else if (status == Status.SUCCESS) {
            bottomProgress.setVisibility(View.GONE);

        } else if (status == Status.PRE_REQUEST) {
            bottomProgress.setVisibility(View.VISIBLE);
        }
    }
}

The Fragment

private TreeBottomListener bottomListener = bottomCallbacks;

private static TreeBottomListener bottomCallbacks = new TreeBottomListener() {
        @Override
        public void onResponse(Status status) {

        }
    };

// I do this say when a network request is about to be sent
bottomListener.onResponse(TreeBottomListener.Status.PRE_REQUEST);
X09
  • 3,827
  • 10
  • 47
  • 92
  • Refer this [link](http://stackoverflow.com/questions/32720702/how-to-call-a-mainactivity-method-from-viewholder-in-recyclerview-adapter) for your reference – vijay chhalotre Mar 01 '17 at 07:58
  • @vijaychhalotre, Thanks. I have seen that before but I want to do is the reverse i.e call ViewHolder method from Fragment/Activity. – X09 Mar 01 '17 at 08:01
  • You should not do this. This will make your code tightly coupled and very complex. Adapter task should be to display items in the list or recyclerView. Activity should not interact with the Adapter or ViewHolder directly. If you wanted to refresh the items of the list make changes to the adapter data list and call notifydatasetChange method. – nnn Mar 01 '17 at 08:31

1 Answers1

4

you can call this method (YourAdapter.TreeBottomViewHolder)recyclerView.findViewHolderForLayoutPosition(position); it returns ViewHolder, you can check about the item position by using the following code:

    private boolean isCurrentListViewItemVisible(int position) {
    LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
    int first = layoutManager.findFirstVisibleItemPosition();
    int last = layoutManager.findLastVisibleItemPosition();
    return first <= position && position <= last;
}

then you can do the following :

TreeBottomViewHolder holder = (YourAdapter.TreeBottomViewHolder)recyclerView.findViewHolderForLayoutPosition(position);

if(isCurrentListViewItemVisible(position)){
    // you can access your views here
}

i wish if it helps you.

mahmoud moustafa
  • 223
  • 3
  • 11