For example, I have a list of items in RecyclerView:

Элемент1 (id1 Title1 Date1) Элемент2 (id2 Title2 Date2) Элемент3 (id3 Title3 Date3) 

It is necessary to open a fragment by clicking on a separate element, to which the corresponding values ​​are transmitted. Suppose you clicked on Элемент2 , a fragment opens and the values ​​of Title2 and Date2 , so that I use them, and so on.
Reading many resources, I don’t understand how to do it all according to science, for in various sources, who as the listener hangs, but I still don’t understand how to organize what I need. I would be grateful for the help! :)

  • You as well as everyone can “hang up” the listener in different ways , depending on the tasks being solved, there is no only correct “according to science” - just as it is more convenient to accomplish exactly your task, so do it. - pavlofff
  • Please see my answer below. Is this a correct way ?! - YaPV

4 answers 4

The communication between the fragments should go through the activit that hosts these fragments. To communicate a fragment with an activation, you need to create an interface, implement it in an activation, in an onAttach fragment, bring the context to the interface, and pull the interface methods during manipulations in the fragment. Activiti can refer to the fragment directly to its methods. Simplified as follows:

 interface ModelOpener { void openModel(Model model); } class MainActivity extends AppCompatActivity implements ModelOpener { @Override void openModel(Model model){ Fragment f = ModelFragment.newInstance(model); getSupportFragmentManager().beginTransaction().replace(..., f).commit(); } } class ModelListFragment extends Fragment { class Holder extends RecyclerView.ViewHolder { ... } @Override void onAttach(Context context){ super.onAttach(context); if(context instanceof ModelOpener){ mModelOpener = (ModelOpener)mModelOpener; } } @Override void onViewCreated(View view){ ... mRecyclerView = (RecyclerView)view.findViewById(R.id.list); } @Override void onActivityCreated(...){ ... adapter = new RecyclerView.Adapter<Holder>(){ ... @Override void onBindVewHolder(Holder holder, position){ holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mModelOpener!=null) mModelOpener.openModel( list.get(holder.getAdapterPosition())); } }); } }; mRecyclerView.setAdapter(adapter); } } class ModelFragment extends Fragment { public static ModelFragment newInstance(Model model){ Bundle args = new Bundle(); // помещаем модель в аргументы. тут как удобно: сериализуем модель Serializable, Parcelable и вообще в Json. или передаем только id, а фрагмент сам например в базе возьмет необходимые данные //например args.putString("title",model.getText()); fragment = new ModelFragment(); fragment.setArguments(args); return fragment; } ... @Override void onActivityCreated(...){ // и здесь достаем аргументы // например mTitleTextView.setText(getArguments().getString("title")); } } 

Threat wrote in the editor window, there may be typos

  • Those. This method is suitable if I have 1 activation with framelayout and 2 fragments, right? I recently started learning Android, a little bit hard to write, but I will try! then I will give the answer :) - YaPV
  • Yes, it is possible in any combination of fragments on the same activation. Read the book of Hardy and Phillips, there are several chapters about it. - Yura Ivanov

In general, I organized this all in the Adapter class, in the onBindViewHolder method:

 @Override public void onBindViewHolder(final Adapter.ViewHolder holder, int position) { Model model = list.get(position); //ArrayList<Model> list; holder.title.setText(model.getText()); holder.date.setText(model.getDate()); holder.view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.d("logs", "title-"+ holder.title.getText()+", date-"+holder.date.getText()); } }); } 

ViewHolder nested class in adapter. Logs show that everything works. By clicking on a single item in the list, get the correct values ​​of the title and date. If there is a smarter way and the main thing is to do it better, then please correct me :)

  • I can say that the data must always be received from the source, not the presentation (not holder.title.getText() , but model.getText() in the log). To launch this, it would be enough, but it would be somewhat problematic to launch a fragment from the adapter. The most acceptable solution in this case will be Yura Ivanov - pavlofff
  • Now I have another question) I did the handling of pressing, ok. And now, when pressed, fill FrameLayout with another fragment :)) because the getSupportFragmentManager () method cannot be called) - YaPV

I would recommend declaring your interface inside the adapter and accepting it in the adapter's constructor.

 public interface Listener{ void onItemClick(int position); //можно добавить и саму модель ,Model model } 

You need to bind the listener in the onCreateViewHolder adapter onCreateViewHolder (which will allow you to avoid multiple recreations of View.OnClickListener objects in the case of the onBindViewHolder method)

 public abstract VH onCreateViewHolder(ViewGroup parent, int viewType) { //... view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { final int pos = holder.getAdapterPosition(); if (pos != RecyclerView.NO_POSITION) { listener.onItemClick(pos); } } }); } 

And in the activation / fragment class itself, where the adapter is used, already and implement the handler. Thus, if you change the processing logic of the press, the adapter code will remain unchanged, only the handler code will change.

    Read what "Intent" is. With it you can transfer data.

    • I have one activation and 2 fragments. in the first fragment, the list of items in recycling, in the second fragment - a detailed description of an individual item - YaPV
    • one
      A usage example would clearly not hurt the answer. - aleksandr barakin