0

Even after some time trying to read and understand the topics already posted here, I am still confused on how to create events in Java.

Assuming that I have this class in C#:

public class HighlightsObjectHandler {
    // Constants
    private const String
        JsonKeysHighlightsHolder = "Items",
        JsonKeysHighlightUrl = "Url",
        JsonKeysHighlightTranslationsHolder = "Traducoes",
        JsonKeysHighlightTranslationLanguage = "Idioma",
        JsonKeysHighlightTranslationText = "Titulo",
        JsonKeysHighlightTranslationImage = "Imagem";

    // Handlers
    public event EventHandler HighlightsJsonChanged;

    public event EventHandler HighlightsContentChanging;
    public event EventHandler HighlightsContentChanged;

    // Variables
    private String
        _json;

    // Properties
    public String HighlightsJson {
        get {
            return _json;
        }
        set {
            if (value != _json && value != null) {
                _json = value;

                OnHighlightsJsonChanged( EventArgs.Empty );

                ParseJson();
            }
        }
    }

    public Boolean HighlightsUpdating { get; private set; }
    public List<HighlightObject> Highlights { get; private set; }

    // Methods
    private void ParseJson() {
        JsonObject
            jsonObject;

        if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
            OnHighlightsContentChanging( EventArgs.Empty );

            // Json parsing and other stuff...
            // ... it shouldn't matter for this question.

            OnHighlightsContentChanged( EventArgs.Empty );
        }
    }

    // Events
    internal void OnHighlightsJsonChanged( EventArgs eventArgs ) {
        if (HighlightsJsonChanged != null) {
            HighlightsJsonChanged( this, eventArgs );
        }
    }

    internal void OnHighlightsContentChanging( EventArgs eventArgs ) {
        HighlightsUpdating = true;

        if (HighlightsContentChanging != null) {
            HighlightsContentChanging( this, eventArgs );
        }
    }
    internal void OnHighlightsContentChanged( EventArgs eventArgs ) {
        HighlightsUpdating = false;

        if (HighlightsContentChanged != null) {
            HighlightsContentChanged( this, eventArgs );
        }
    }

    // Constructors
    public HighlightsObjectHandler() {
        Highlights = new List<HighlightObject>();
    }
}

How would I make a copy of this in Java?

I somewhat understand that I need to create an interface that would hold the 3 EventHandlers that I have in this code. Then, I would have to implement that interface in the class. Let's assume that the class would have the exact same name and the result would be something like this:

    public class HighlightsObjectHandler implements SomeListener { ... }

But, from what I see from tutorials and forums, they would fire, for instance, the HighlightsContentChanging directly instead of calling the OnHighlightsContentChanging ( where I would like to set a variable - HighlightsUpdating - to a value and then calling the listeners associated with the event ).

And there is where I'm losing my mind. How would I make this happen? In the Windows Phone app, that variable would help me whenever a page that had this content in it to set the page as loading or to display a message if the page has nothing to show.

UPDATE:

I've managed to create the code I as able to, or had acknowledge to. I'll leave here the code so far:

package com.example.nlsonmartins.myapplication.Highlights;

import java.util.ArrayList;
import org.json.*;

public class HighlightsObjectHandler {
    // Constants
    private final String
              JsonKeysHighlightsHolder = "Items",
              JsonKeysHighlightUrl = "Url",
              JsonKeysHighlightTranslationsHolder = "Traducoes",
              JsonKeysHighlightTranslationLanguage = "Idioma",
              JsonKeysHighlightTranslationText = "Titulo",
              JsonKeysHighlightTranslationImage = "Imagem";

    // Enumerators

    // Handlers

    // Variables
    private String
              _json;
    private Boolean
              _updating;
    private ArrayList<HighlightObject>
              _highlights;

    // Properties
    public String HighlightsJson() {
        return _json;
    }
    public void HighlightsJson(String highlightsJson) {
        // Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
        if(highlightsJson != _json && highlightsJson != null) {
            _json = highlightsJson;

            // Fire the Java equivalent of C# 'OnHighlightsJsonChanged( EventArgs.Empty );'

            ParseJson();
        }
    }

    public Boolean HighlightsUpdating() {
        return _updating;
    }
    private void HighlightsUpdating(Boolean isUpdating) {
        _updating = isUpdating;
    }

    public ArrayList<HighlightObject> Highlights() {
        return _highlights;
    }

    // Methods
    private void ParseJson() {
        try {
            JSONObject
                      jsonObject = new JSONObject(HighlightsJson());

            // Fire the Java equivalent of C# 'OnHighlightsContentsChanging( EventArgs.Empty );'

            // Parse the JSON object

            // Fire the Java equivalent of C# 'OnHighlightsContentsChanged( EventArgs.Empty );'
        } catch (JSONException exception) {

        }
    }

    // Events

    /* Create the event handler for 'OnHighlightsJsonChanged' */

    /* Create the event handler for 'OnHighlightsContentsChanging' and call the 'HighlightsUpdating(true);' method  */
    /* Create the event handler for 'OnHighlightsContentsChanged' and call the 'HighlightsUpdating(false);' method  */

    // Constructors
    public HighlightsObjectHandler() {
        _highlights = new ArrayList<HighlightObject>();
    }
}
auhmaan
  • 726
  • 1
  • 8
  • 28

3 Answers3

1

I don't have an equivalent for the 'JsonObject' type, but other than that I think the following may work for you, using your own custom EventHandler functional interface, custom EventArgs class, and generic 'Event' helper class:

import java.util.*;

public class HighlightsObjectHandler
{
    // Constants
    private static final String JsonKeysHighlightsHolder = "Items",
        JsonKeysHighlightUrl = "Url",
        JsonKeysHighlightTranslationsHolder = "Traducoes",
        JsonKeysHighlightTranslationLanguage = "Idioma",
        JsonKeysHighlightTranslationText = "Titulo",
        JsonKeysHighlightTranslationImage = "Imagem";

    // Handlers
    public Event<CustomEventHandler> HighlightsJsonChanged = new Event<CustomEventHandler>();

    public Event<CustomEventHandler> HighlightsContentChanging = new Event<CustomEventHandler>();
    public Event<CustomEventHandler> HighlightsContentChanged = new Event<CustomEventHandler>();

    // Variables
    private String _json;

    // Properties
    public final String getHighlightsJson()
    {
        return _json;
    }
    public final void setHighlightsJson(String value)
    {
        if (!_json.equals(value) && value != null)
        {
            _json = value;

            OnHighlightsJsonChanged(CustomEventArgs.Empty);

            ParseJson();
        }
    }

    private boolean HighlightsUpdating;
    public final boolean getHighlightsUpdating()
    {
        return HighlightsUpdating;
    }
    private void setHighlightsUpdating(boolean value)
    {
        HighlightsUpdating = value;
    }
    private ArrayList<HighlightObject> Highlights;
    public final ArrayList<HighlightObject> getHighlights()
    {
        return Highlights;
    }
    private void setHighlights(ArrayList<HighlightObject> value)
    {
        Highlights = value;
    }

    // Methods
    private void ParseJson()
    {
        //todo: no equivalent to 'JsonObject':
        JsonObject jsonObject = null;

        //todo: no equivalent to 'out' parameter:
        if (JsonObject.TryParse(HighlightsJson, jsonObject))
        {
            OnHighlightsContentChanging(CustomEventArgs.Empty);

            // Json parsing and other stuff...
            // ... it shouldn't matter for this question.

            OnHighlightsContentChanged(CustomEventArgs.Empty);
        }
    }

    // Events
    public final void OnHighlightsJsonChanged(CustomEventArgs eventArgs)
    {
        if (HighlightsJsonChanged != null)
        {
            for (CustomEventHandler listener : HighlightsJsonChanged.listeners())
            {
                listener.invoke(this, eventArgs);
            }
        }
    }

    public final void OnHighlightsContentChanging(CustomEventArgs eventArgs)
    {
        setHighlightsUpdating(true);

        if (HighlightsContentChanging != null)
        {
            for (CustomEventHandler listener : HighlightsContentChanging.listeners())
            {
                listener.invoke(this, eventArgs);
            }
        }
    }
    public final void OnHighlightsContentChanged(CustomEventArgs eventArgs)
    {
        setHighlightsUpdating(false);

        if (HighlightsContentChanged != null)
        {
            for (CustomEventHandler listener : HighlightsContentChanged.listeners())
            {
                listener.invoke(this, eventArgs);
            }
        }
    }

    // Constructors
    public HighlightsObjectHandler()
    {
        setHighlights(new ArrayList<HighlightObject>());
    }
}

@FunctionalInterface
public interface CustomEventHandler
{
    void invoke(object sender, CustomEventArgs e);
}
public class CustomEventArgs
{
    public static readonly CustomEventArgs Empty;

    public CustomEventArgs()
    {
    }
}

//this is produced as a helper class by C# to Java Converter:
public final class Event<T>
{
    private java.util.Map<String, T> namedListeners = new java.util.HashMap<String, T>();
    public void addListener(String methodName, T namedEventHandlerMethod)
    {
        if (!namedListeners.containsKey(methodName))
            namedListeners.put(methodName, namedEventHandlerMethod);
    }
    public void removeListener(String methodName)
    {
        if (namedListeners.containsKey(methodName))
            namedListeners.remove(methodName);
    }

    private java.util.List<T> anonymousListeners = new java.util.ArrayList<T>();
    public void addListener(T unnamedEventHandlerMethod)
    {
        anonymousListeners.add(unnamedEventHandlerMethod);
    }

    public java.util.List<T> listeners()
    {
        java.util.List<T> allListeners = new java.util.ArrayList<T>();
        allListeners.addAll(namedListeners.values());
        allListeners.addAll(anonymousListeners);
        return allListeners;
    }
}
Dave Doknjas
  • 6,394
  • 1
  • 15
  • 28
  • Wow... This is **exactly** what I was searching for! You even created an `Event` class to mimic the C# one ( I would never think on something like that ). I'll just wait until Monday to check other answers give by the community, but this one seems to be the one that will deserve more the 'Answer' tag. – auhmaan Mar 18 '16 at 18:13
  • @N.Martins: No problem - as I mentioned in the code comment, the 'Event' helper class is produced by our converter, so that part was already available. – Dave Doknjas Mar 18 '16 at 18:19
0

import java.util.*; interface HelloListener { void someoneSaidHello();}

Muhammad_08
  • 140
  • 2
  • 12
0

NOTE

I'm going to have this StackOverflow answer as a base for what I'm going to explain in this answer.


Okay, so, for what I could read and understand, it isn't that much different building C#-like events in Java ( or, in another point of view, it isn't that hard from someone who develops in C# to build events in Java ).

First, from my perspective, I'd like to point that the way I build the events in Java are almost a copy-paste from C# ( maybe it's the correct way to do it, maybe it isn't ).

Second, I'm going to - hopefully - put this in a way people might understand ( based on tutorials I saw here on StackOverflow and other sites ):

  • The events on C# are wrapped in a method that is set as internal - usually the OnSomethingChanging or OnSomethingChanged - whereas the Java events are not. Imagine this method in Java:

    List<HelloListener> listeners = new ArrayList<HelloListener>();
    
    public void sayHello() {
        System.out.println("Hello!!");
    
        // Notify everybody that may be interested.
        for (HelloListener hl : listeners)
            hl.someoneSaidHello();
    }
    

    Now, to make it more C# like, I would to make it like this:

    public event EventHandler HelloListener;
    
    public void SayHello() {
        Console.WriteLine("Hello!!");
    
        // Notify everybody that may be interested.
        if(HelloListener != null) {
            HelloListener(this, EventArgs.Empty);
        }
    }
    

    Basically I was expecting to have to make an OnHelloListener method, then trigger the events on that very method but, on the majority of examples and tutorials that I saw, they would do something like I wrote above. That was what was messing my head really badly ( and probably others too if they come from C# to Java ).


In conclusion

If I was to translate the HighlightsObjectHandler class from C# to Java - and keeping the C# soul in it - I would end with something like this:

public class HighlightsObjectHandler {
    // Constants
    private final String
              JsonKeysHighlightsHolder = "Items",
              JsonKeysHighlightUrl = "Url",
              JsonKeysHighlightTranslationsHolder = "Traducoes",
              JsonKeysHighlightTranslationLanguage = "Idioma",
              JsonKeysHighlightTranslationText = "Titulo",
              JsonKeysHighlightTranslationImage = "Imagem";

    // Enumerators

    // Handlers
    private List<HighlightsListener>
              _highlightsListeners = new ArrayList<HighlightsListener>();

    // Variables
    private String
              _json;
    private Boolean
              _updating;
    private List<HighlightObject>
              _highlights;

    // Properties
    public String HighlightsJson() {
        return _json;
    }
    public void HighlightsJson(String highlightsJson) {
        // Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
        if (!highlightsJson.equals(_json) && highlightsJson != null) {
            _json = highlightsJson;

            OnHighlightsJsonChanged();

            ParseJson();
        }
    }

    public Boolean HighlightsUpdating() {
        return _updating;
    }
    private void HighlightsUpdating(Boolean isUpdating) {
        _updating = isUpdating;
    }

    public List<HighlightObject> Highlights() {
        return _highlights;
    }

    // Methods
    private void ParseJson() {
        if (HighlightsUpdating()) {
            return;
        }

        try {
            OnHighlightsContentsChanging();

            // Parse the JSON object

            OnHighlightsContentsChanged();
        } catch (JSONException exception) {

        }
    }

    // Events
    private void OnHighlightsJsonChanged() {
        for(HighlightsListener highlightsListener : _highlightsListeners) {
            highlightsListener.HighlightsJsonChanged();
        }
    }

    private void OnHighlightsContentsChanging() {
        HighlightsUpdating(true);

        for(HighlightsListener highlightsListener : _highlightsListeners) {
            highlightsListener.HighlightsContentChanging();
        }
    }
    private void OnHighlightsContentsChanged() {
        HighlightsUpdating(false);

        for(HighlightsListener highlightsListener : _highlightsListeners) {
            highlightsListener.HighlightsContentChanged();
        }
    }

    // Constructors
    public HighlightsObjectHandler() {
        _highlights = new List<HighlightObject>();
    }
}

Once again, my problem was basically me expecting to have to create the OnSomethingChanged methods that would trigger the events and not the code directly placed on the methods when I want them to be triggered.

You could say that I was an app that was crashing when you typed this while expecting you to type that.


Java to C#

WARNING If you're easily confused or you're still trying to understand this, I recommend you to not read this part of the answer. This is just an for fun and curiosity block that I found somewhat funny and interesting...

So, let's say that my problem was the opposite that is now, I had a Java class with events and would like to translate it to C#. From what I know to this point I would end with something like this in C#:

public class HighlightsObjectHandler {
    // Constants
    private const String
        JsonKeysHighlightsHolder = "Items",
        JsonKeysHighlightUrl = "Url",
        JsonKeysHighlightTranslationsHolder = "Traducoes",
        JsonKeysHighlightTranslationLanguage = "Idioma",
        JsonKeysHighlightTranslationText = "Titulo",
        JsonKeysHighlightTranslationImage = "Imagem";

    // Enumerators

    // Handlers
    public event EventHandler HighlightsJsonChanged;

    public event EventHandler HighlightsContentChanging;
    public event EventHandler HighlightsContentChanged;

    // Variables
    private String
        _json;

    // Properties
    public String HighlightsJson {
        get {
            return _json;
        }
        set {
            if (value != _json && value != null) {
                _json = value;

                if (HighlightsJsonChanged != null) {
                    HighlightsJsonChanged( this, eventArgs );
                }

                ParseJson();
            }
        }
    }

    public Boolean HighlightsUpdating { get; private set; }
    public List<HighlightObject> Highlights { get; private set; }

    // Methods
    private void ParseJson() {
        JsonObject
            jsonObject;

        if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
            HighlightsUpdating = true;
            if (HighlightsContentChanging != null) {
                HighlightsContentChanging( this, eventArgs );
            }

            // Json parsing

            HighlightsUpdating = false;
            if (HighlightsContentChanged != null) {
                HighlightsContentChanged( this, eventArgs );
            }
        }
    }

    // Events

    // Constructors
    public HighlightsObjectHandler() {
        Highlights = new List<HighlightObject>();
    }
}

Note how instead the OnHighlightsJsonChanged and the other internal methods are removed and, instead of having the code I had on the methods they are instead where I called the methods.

P.S.: I will mark this answer as the answer to the this question on the next Monday so I can see others answers and select one of them if they fit more as a final answer.

Community
  • 1
  • 1
auhmaan
  • 726
  • 1
  • 8
  • 28