Suppose I have a RecyclerView adapter and activity in different files. How do I properly implement the method call in activity from the adapter? So far implemented as:

https://github.com/ATumbler/Notepad/blob/master/app/src/main/java/ru/albatros/notepad/NotesAdapter.java

I transfer the context to the adapter, bring it to the activity class and call the methods.

I heard about kolbeki, but I don’t understand what it is and how to do it.

    2 answers 2

    A somewhat unusual implementation is proposed in another answer .. I will write a more classic solution.

    For a start, what’s wrong with calling the activation methods from the adapter and why it’s bad. The fact is that the activator is a kontroller of what is displayed on the screen and it should act as the initiator of the actions of the widgets located on it (the adapter is part of the widget for displaying the list). If you turn to an abstract example, then when you call the activation methods from the adapter, you get something like the fact that the mailbox "sucks" the apartment with you, so that you can check your mail, instead of you going there to look. This solution does not look very much.
    The general sense is that the control should initiate actions, and not events affect the control (the remote control programs in the TV, not the program to switch channels)

    The methods of interaction with the adapter depend on the type of interaction - whether an event occurs in the widget (for example, click on an element or in an abstract example - whether the mail arrived in the mailbox), which needs to be activated or activated, some information / action is required from the widget, for example, the data displayed in a widget or an update in the list.

    In the first case, a callback mechanism is used (callback interface). In the abstract example, we will install a sensor in the box that coordinates the presence of mail.
    This mechanism is designed so that by calling the interface method in one place of the code, it is automatically called in another place that implements this callback interface. In this case, the arguments received in the method of communication initiator are transferred to the receiver method and you can transfer data associated with the event (for example, record ID).

    Typical callback.

    In the adapter:

     class SomeAdapter extends RecyclerView.Adapter <Data, SomeAdapter.ItemHolder> { // создаСм сам интСрфСйс ΠΈ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹Π΅ ΠΈΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ // View Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ событиС ΠΈ позиция этого View interface OnCardClickListener { void onCardClick(View view, int position); } // создаСм ΠΏΠΎΠ»Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°-колбэка private static OnCardClickListener mListener; public SomeAdapter (Data data) { // конструктор Π°Π΄Π°ΠΏΡ‚Π΅Ρ€Π° } @Override public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { .... return new ItemHolder(v); } @Override public void onBindViewHolder( ItemHolder holder, int position) { ..... } // ΠΌΠ΅Ρ‚ΠΎΠ΄-сСттСр для привязки колбэка ΠΊ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚Π΅Π»ΡŽ событий public void setOnCardClickListener(OnCardClickListener listener) { mListener = listener; } public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ CardView mCard; public ItemHolder(View v) { super(v); mCard = (CardView) v.findViewById(R.id.bell_card); // само событиС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ (ΠΊΠ»ΠΈΠΊ Π½Π° элСмСнтС) mCard.setOnClickListener(this); } // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ события @Override public void onClick(View v) { // Π²Ρ‹Π·ΠΎΠ² ΠΌΠ΅Ρ‚ΠΎΠ΄Π°-колбэка ΠΈ Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌ int position = getAdapterPosition(); mListener.onCardClick(v, position); } } } 

    In activit:

     // ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ наш интСрфСйс ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° Π² Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ‚ΠΈ public class SomeActiviy extends Activity implements SomeAdapter.OnCardClickListener { Data data; ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAdapter = new SomeAdapter(data); // подписываСм Π½Π°ΡˆΡƒ Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ‚ΠΈ Π½Π° события колбэка mAdapter.setOnCardClickListener(this); mList.setAdapter(mAdapter); } // ΠΌΠ΅Ρ‚ΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ события ΠΈΠ· нашСго колбэка @Override public void onCardClick(View view,final int pos) { // здСсь ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ событиС, значСния View ΠΈ pos // Ρ€Π°Π²Π½Ρ‹ значСниям, присвоСнным Π² Π°Π΄Π°ΠΏΡ‚Π΅Ρ€Π΅ } } 

    The second option is much simpler, we just create methods in the adapter that will return the data we need or will cause certain actions in the adapter when they are required to be activated. That is, it’s not the adapter that calls activation methods, but it activates the adapter methods when it needs information / actions from it:

    in adapter:

     class SomeAdapter extends RecyclerView.Adapter <Data, SomeAdapter.ItemHolder> { // ΠΌΠ΅Ρ‚ΠΎΠ΄ обновлСния списка ΠΏΠΎ Π½ΠΎΠ²ΠΎΠΌΡƒ Π½Π°Π±ΠΎΡ€Ρƒ Π΄Π°Π½Π½Ρ‹Ρ… public void notifyData(Data result) { mData = result; notifyDataSetChanged(); } // ΠΌΠ΅Ρ‚ΠΎΠ΄ получСния Ρ€Π°Π·ΠΌΠ΅Ρ€Π° списка public int getSize() { return mData.size(); } } 

    In activit:

     public class SomeActiviy extends Activity { Data data; ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAdapter = new SomeAdapter(data); mList.setAdapter(mAdapter); // Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ‚ΠΈ трСбуСтся Ρ€Π°Π·ΠΌΠ΅Ρ€ списка int size = mAdapter.getSize(); // Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ‚ΠΈ трСбуСтся ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ список с вновь ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΌΠΈ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ Data data = getData(); mAdapter.notifyData(data); } } 
    • Your answer is better :) Moved a tick, thanks, now everything is clear - Flippy

    1) Inside your NotesAdapter class, create an interface and reserve a variable.

      public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.AdapterHolder> { public interface INotesAdapterCallback { void openEditor(String text, String color, long id, int position); void delete(long id); } INotesAdapterCallback callback; Cursor cursor; ... } 

    2) In your activity, add the implementation of this interface.

     public class NotepadActivity extends AppCompatActivity implements INotesAdapterCallback 

    3) Immediately after this, the Studio will offer you to implement the methods of the interface (it will highlight the title in red, when you click on alt + enter it will offer to add methods). Do it.

    1. In the adapter, in the constructor, transfer not the context (this is a memory leak), but an instance of the object that implements the interface.

      NotesAdapter (Cursor cursor, INotesAdapterCallback callback) {this.cursor = cursor; this.callback = callback; }

    2. When working with Holder, refer to the callback variable.

      public void onClick (View v) {if (callback! = null) callback.openEditor (text, color, id, position); }

    3. Calling the adapter from the activity now looks like this: notes_adapter = new NotesAdapter (cursor, this);

    • Thank you, figured out - Flippy
    • Thanks, it works for me. And it is very easy to use)))) - Vitaly Robinovsky