How to send data from recycler adapter to fragment

2020-03-25 05:01发布

问题:

I have code in Fragment:

InfoAdapter adapter = new InfoAdapter(getContext(), R.layout.lv_info, infoList );

            listingsView = (RecyclerView) rootView.findViewById(R.id.lvInfo);
            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
            listingsView.setLayoutManager(layoutManager);
            listingsView.setHasFixedSize(true);
            listingsView.setAdapter(adapter);

How do I process clicks on an items in this fragment? Eg call function (function located in fragment) with ID item (eg public void onItemClick(int item_id) {} )

My adapter:

public class InfoAdapter extends RecyclerView.Adapter<InfoHolder> {

    private final List<Info> infos;
    private Context context;
    private int itemResource;


    public InfoAdapter(Context context, int itemResource, List<Info> infos) {

        this.infos = infos;
        this.context = context;
        this.itemResource = itemResource;
    }

    @Override
    public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext())
                .inflate(this.itemResource, parent, false);
        return new InfoHolder(this.context, view);
    }

    @Override
    public void onBindViewHolder(InfoHolder holder, int position) {

        Info info = this.infos.get(position);
        holder.bindInfo(info);
    }

    @Override
    public int getItemCount() {
        return this.infos.size();
    }
 }

回答1:

You can use interface to achieve your desired result. Just declare an interface in your adapter with the parameters that you want to pass to your fragment. And in your fragment initialize the interface and pass it to your adapter's constructor.

You can do something like this:

In your Fragment

public class MainFragment extends Fragment {

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

    // Pass your adapter interface in the constructor
    InfoAdapter adapter = new InfoAdapter(getContext(), R.layout.lv_info, infoList, adapterInterface );
}

// This is the interface declared inside your adapter.
InfoAdapter.InfoAdapterInterface adapterInterface = new InfoAdapter.InfoAdapterInterface() {
    @Override
    public void OnItemClicked(int item_id) {
        // Do whatever you wants to do with this data that is coming from your adapter
    }
};

}

In your Adapter

public class InfoAdapter extends RecyclerView.Adapter<InfoHolder> {

    private final List<Info> infos;
    private Context context;
    private int itemResource;

    // Interface Object
    private InfoAdapterInterface adapterInterface;

    public InfoAdapter(Context context, int itemResource, List<Info> infos, InfoAdapterInterface adapterInterface) {

        this.infos = infos;
        this.context = context;
        this.itemResource = itemResource;

        // Initialize your interface to send updates to fragment.
        this.adapterInterface = adapterInterface;
    }

    @Override
    public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext())
                .inflate(this.itemResource, parent, false);
        return new InfoHolder(this.context, view);
    }

    @Override
    public void onBindViewHolder(InfoHolder holder, int position) {

        Info info = this.infos.get(position);
        holder.bindInfo(info);

        // You can pass any data here that is defined in your interface's params
        adapterInterface.OnItemClicked(3);
    }

    @Override
    public int getItemCount() {
        return this.infos.size();
    }

    // Your interface to send data to your fragment
    public interface InfoAdapterInterface{
        void OnItemClicked(int item_id);
    }

 }

You can create multiple methods in your interface and can easily get the desired data inside your interface. Another trick can be using Abstract methods.

I hope this will help you. Let me know if you face any difficulty :)


Edit to show how to pass Interface from Adapter to ViewHolder

In your Adapter Class do this

@Override
public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext())
            .inflate(this.itemResource, parent, false);

    // Pass the interface that you've created in the constructor of your viewholder
    return new InfoHolder(view, adapterInterface);
}

And in your ViewHolder you can get the interface like this and use it wherever you want inside your ViewHolder:

public class InfoHolder extends RecyclerView.ViewHolder {

    public InfoHolder(View itemView, final InfoAdapter.InfoAdapterInterface adapterInterface) {
        super(itemView);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                adapterInterface.OnItemClicked(2);

            }
        });

    }

}

This should solve your problem with interfaces ^_^



回答2:

In your method onBindViewHolder, set the onclicklistener in the binded view and pass its parameters trough Bundle.



回答3:

Just pass Fragment instance to adapter.

For example :

IN FRAGMENT : recyclerAdapter = new RecyclerAdapter(getActivity(), MyFragment.this); recyclerView.setAdapter(recyclerAdapter); recyclerAdapter.notifyDataSetChanged(); IN ADAPTER : 1. Create adapter constructer like

MyFragment myFragment;
public RecyclerAdapter(Context context, MyFragment myFragment){
    this.context = context;
    this.myFragment = myFragment;
}
  1. under onBindViewHolder

call myFragment.yourMethodName;