149

Could someone help me to create user defined listener interface with some code snippets?

Akhil
  • 107
  • 9
Rajapandian
  • 7,059
  • 11
  • 37
  • 27

9 Answers9

211

Create a new file:

MyListener.java:

public interface MyListener {
    // you can define any parameter as per your requirement
    public void callback(View view, String result);
}

In your activity, implement the interface:

MyActivity.java:

public class MyActivity extends Activity implements MyListener {
   @override        
   public void onCreate(){
        MyButton m = new MyButton(this);
   }

    // method is invoked when MyButton is clicked
    @override
    public void callback(View view, String result) {   
        // do your stuff here
    }
}

In your custom class, invoke the interface when needed:

MyButton.java:

public class MyButton {
    MyListener ml;

    // constructor
    MyButton(MyListener ml) {
        //Setting the listener
        this.ml = ml;
    }

    public void MyLogicToIntimateOthers() {
        //Invoke the interface
        ml.callback(this, "success");
    }
}
Ali Bdeir
  • 4,151
  • 10
  • 57
  • 117
Rakesh Soni
  • 10,135
  • 5
  • 44
  • 51
  • 3
    How to pass the Listener Object if our Button is already in the layout rather we don't used the MyButton m = new MyButton(this); way to create the object of Button. – Qadir Hussain Dec 07 '15 at 07:25
  • 2
    You can add a new method in MyButton class : void setMyListener(MyListner m1){ this.ml = m1;} and then use this method any time to set your listener object. – Rakesh Soni Dec 07 '15 at 10:22
  • 1
    where is MyLogicToIntimateOthere() this method used ? – abh22ishek May 24 '16 at 10:59
  • 2
    Coming from an iOS background, if i did this in iOS it would cause a memory leak because the MyButton's listener is a strong reference to the listener, and the listener has a strong reference to the MyButton... is java garbage collector clever enough to know that both the listener and the MyButton should be cleaned up if there are no references to the listener left other than from the MyButton? You could use a `WeakReference<>` in this case, but then you cant make the listener an anonymous class or anything where the listener has no other references... so it would be preferable not to use it – Fonix Sep 15 '16 at 04:32
  • where is MyLogicToIntimateOthers() used – Ali Bdeir Jul 31 '18 at 21:08
119

please do read observer pattern

listener interface

public interface OnEventListener {
    void onEvent(EventResult er);
    // or void onEvent(); as per your need
}

then in your class say Event class

public class Event {
    private OnEventListener mOnEventListener;

    public void setOnEventListener(OnEventListener listener) {
        mOnEventListener = listener;
    }

    public void doEvent() {
        /*
         * code code code
         */

         // and in the end

         if (mOnEventListener != null)
             mOnEventListener.onEvent(eventResult); // event result object :)
    }
}

in your driver class MyTestDriver

public class MyTestDriver {
    public static void main(String[] args) {
        Event e = new Event();
        e.setOnEventListener(new OnEventListener() {
             public void onEvent(EventResult er) {
                 // do your work. 
             }
        });
        e.doEvent();
    }
}
Rupesh
  • 3,415
  • 2
  • 26
  • 30
11

I have created a Generic AsyncTask Listener which get result from AsycTask seperate class and give it to CallingActivity using Interface Callback.

new GenericAsyncTask(context,new AsyncTaskCompleteListener()
        {
             public void onTaskComplete(String response) 
             {
                 // do your work. 
             }
        }).execute();

Interface

interface AsyncTaskCompleteListener<T> {
   public void onTaskComplete(T result);
}

GenericAsyncTask

class GenericAsyncTask extends AsyncTask<String, Void, String> 
{
    private AsyncTaskCompleteListener<String> callback;

    public A(Context context, AsyncTaskCompleteListener<String> cb) {
        this.context = context;
        this.callback = cb;
    }

    protected void onPostExecute(String result) {
       finalResult = result;
       callback.onTaskComplete(result);
   }  
}

Have a look at this , this question for more details.

Community
  • 1
  • 1
Xar-e-ahmer Khan
  • 1,314
  • 15
  • 23
9

There are 4 steps:

1.create interface class (listener)

2.use interface in view 1 (define variable)

3.implements interface to view 2 (view 1 used in view 2)

4.pass interface in view 1 to view 2

Example:

Step 1: you need create interface and definde function

public interface onAddTextViewCustomListener {
    void onAddText(String text);
}

Step 2: use this interface in view

public class CTextView extends TextView {


    onAddTextViewCustomListener onAddTextViewCustomListener; //listener custom

    public CTextView(Context context, onAddTextViewCustomListener onAddTextViewCustomListener) {
        super(context);
        this.onAddTextViewCustomListener = onAddTextViewCustomListener;
        init(context, null);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    public void init(Context context, @Nullable AttributeSet attrs) {

        if (isInEditMode())
            return;

        //call listener
        onAddTextViewCustomListener.onAddText("this TextView added");
    }
}

Step 3,4: implements to activity

public class MainActivity extends AppCompatActivity implements onAddTextViewCustomListener {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //get main view from layout
        RelativeLayout mainView = (RelativeLayout)findViewById(R.id.mainView);

        //create new CTextView and set listener
        CTextView cTextView = new CTextView(getApplicationContext(), this);

        //add cTextView to mainView
        mainView.addView(cTextView);
    }

    @Override
    public void onAddText(String text) {
        Log.i("Message ", text);
    }
}
Rasoul Miri
  • 11,234
  • 1
  • 68
  • 78
7

Create listener interface.

public interface YourCustomListener
{
    public void onCustomClick(View view);
            // pass view as argument or whatever you want.
}

And create method setOnCustomClick in another activity(or fragment) , where you want to apply your custom listener......

  public void setCustomClickListener(YourCustomListener yourCustomListener)
{
    this.yourCustomListener= yourCustomListener;
}

Call this method from your First activity, and pass the listener interface...

Piyush
  • 18,895
  • 5
  • 32
  • 63
Kapil Vij
  • 312
  • 2
  • 7
6

In the year of 2018, there's no need for listeners interfaces. You've got Android LiveData to take care of passing the desired result back to the UI components.

If I'll take Rupesh's answer and adjust it to use LiveData, it will like so:

public class Event {

    public LiveData<EventResult> doEvent() {
         /*
          * code code code
          */

         // and in the end

         LiveData<EventResult> result = new MutableLiveData<>();
         result.setValue(eventResult);
         return result;
    }
}

and now in your driver class MyTestDriver:

public class MyTestDriver {
    public static void main(String[] args) {
        Event e = new Event();
        e.doEvent().observe(this, new  Observer<EventResult>() {
            @Override
            public void onChanged(final EventResult er) {
                // do your work.
            }
        });
    }
}

For more information along with code samples you can read my post about it, as well as the offical docs:

When and why to use LiveData

Official docs

TheCodeFather
  • 194
  • 1
  • 7
1

In Android,you can create an interface such as Listener,and your Activity implements it,but i don't think it is a good idea. if we have many components to listen the changes of their state,we can create a BaseListener implements interface Listener,and use type code to handle them. we can bind the method when we create XML file,for example:

<Button  
        android:id="@+id/button4"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:text="Button4"  
        android:onClick="Btn4OnClick" />

and the source code:

 public void Btn4OnClick(View view) {  
        String strTmp = "点击Button04";  
        tv.setText(strTmp);  
    }  

but i don't think it is a good idea...

user3055973
  • 49
  • 1
  • 3
0

I have done it something like below for sending my model class from the Second Activity to First Activity. I used LiveData to achieve this, with the help of answers from Rupesh and TheCodeFather.

Second Activity

public static MutableLiveData<AudioListModel> getLiveSong() {
        MutableLiveData<AudioListModel> result = new MutableLiveData<>();
        result.setValue(liveSong);
        return result;
    }

"liveSong" is AudioListModel declared globally

Call this method in the First Activity

PlayerActivity.getLiveSong().observe(this, new Observer<AudioListModel>() {
            @Override
            public void onChanged(AudioListModel audioListModel) {
                if (PlayerActivity.mediaPlayer != null && PlayerActivity.mediaPlayer.isPlaying()) {
                    Log.d("LiveSong--->Changes-->", audioListModel.getSongName());
                }
            }
        });

May this help for new explorers like me.

Deepak J
  • 184
  • 1
  • 7
-4

Simple method to do this approach. Firstly implements the OnClickListeners in your Activity class.

Code:

class MainActivity extends Activity implements OnClickListeners{

protected void OnCreate(Bundle bundle)
{    
    super.onCreate(bundle);    
    setContentView(R.layout.activity_main.xml);    
    Button b1=(Button)findViewById(R.id.sipsi);    
    Button b2=(Button)findViewById(R.id.pipsi);    
    b1.SetOnClickListener(this);    
    b2.SetOnClickListener(this);    
}

public void OnClick(View V)    
{    
    int i=v.getId();    
    switch(i)    
    {    
        case R.id.sipsi:
        {
            //you can do anything from this button
            break;
        }
        case R.id.pipsi:
        {    
            //you can do anything from this button       
            break;
        }
    }
}
Draken
  • 3,134
  • 13
  • 34
  • 54