Please note: I am new in this subject.
Suppose I have a class Event.
public class Event {
//constructors, etc.
public void pathFollowed(int location) {
//this method could be called at any time
}
}
And a class called EventManager.
public class EventManager {
private int managerLocation;
private ArrayList<Event> events;
public EventManager() {
events = new ArrayList<Event>();
}
public void addEvent(Event e) {
//THIS IS THE AREA OF INTEREST
events.add(e);
}
}
In the "area of interest" comment, is there any way of setting the value of managerLocation whenever the Event e calls upon pathFollowed(int location). My goal is that when any of the Events in the events arraylist calls pathFollowed(int location) that managerLocation would be set to "location" ("location" referring to the input in the pathfollowed method).
I was originally thinking of over-riding the pathFollowed method, but then I realized this can't be done because by the time the event gets to the addEvent method, it is already instantiated and can't be changed in this manner.
Thanks in advance.
Maybe some kind of listener pattern?
public class Event {
private List<PathListener> pls; //Or just one if you know you'll only need one
//constructors, etc.
public void pathFollowed(int location) {
//this method could be called at any time
for(PathListener pl : pls)
pl.notifyLocation(location);
}
public addPathListener(PathListener pl) {
pls.add(pl);
}
}
EventManager:
public class EventManager implements PathListener {
private int managerLocation;
private ArrayList<Event> events;
public EventManager() {
events = new ArrayList<Event>();
}
public void addEvent(Event e) {
e.addPathListener(this);
events.add(e);
}
#Override
public notifyLocation(int location) { //Of the PathListener interface
managerLocation = location;
}
}
This is just a kind-of-generic example, because I don't know what your purpose is, but maybe it will get you thinking.
Related
So I'm using the Observer pattern in my app in order to get notified of changes in another class without having to look for them.
I have a Singleton class which extends Observable. Inside this class I have two CountDownTimer type variables. Eachs of these contains two methods: onTick() and onFinished().
Let's call those Timers A and B for the sake of simplicity.
Every time A.onTick(), A.onFinished(), B.onTick(), B.onFinished() are called, I must call notifyObservers() to notify my Observer that something has changed.
Until here everything works fine. The problem is that I know something has changed, but I don't know what exactly has changed. Depending on which one notified me, I must execute some code on the Observer side.
How do I know which of these methods notified me?
Use LiveData instead of Observable. LiveData is quite useful because not only it's observable but also it binds to your activity's lifecycle so you don't have to worry about handling it yourself.
Maybe this example will help you:
public class MyTimerWrapper {
public static MyTimerWrapper getInstance() {
// Your singleton logic
createTimers();
return instance;
}
private CountDownTimer timerA;
private CountDownTimer timerB;
private MutableLiveData<TimerEvent> timerALiveData = new MutableLiveData<TimerEvent>();
private MutableLiveData<TimerEvent> timerBLiveData = new MutableLiveData<TimerEvent>();
public LiveData<TimerEvent> startTimerA() {
timerA.start();
return timerALiveData;
}
public LiveData<TimerEvent> startTimerB() {
timerB.start();
return timerBLiveData;
}
private void createTimers() {
createTimerA();
createTimerB();
}
private void createTimerA() {
timerA = new CountDownTimer(30000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
// If you're running on another thread
timerALiveData.postValue(TimerEvent.TICK);
// Otherwise
timerALiveData.setValue(TimerEvent.TICK);
}
#Override
public void onFinish() {
// If you're running on another thread
timerALiveData.postValue(TimerEvent.FINISH);
// Otherwise
timerALiveData.setValue(TimerEvent.FINISH);
}
}
}
private void createTimerB() {
// Same as createTimerA, but with timerB
}
}
public enum TimerEvent {
TICK,
FINISH
}
Now to observe that data in your activity:
MyTimerWrapper timerWrapper = MyTimerWrapper.getInstance();
timerWrapper.startTimerA().observe(this, new Observer {
#Override
public void onChanged(TimerEvent timerEvent) {
// Here you'll be able to see whether timerA is ticking or finished
}
})
You can create a custom EventType class and pass it to Observable.notifyObservers(Object arg):
public class EventType {
String eventType; //"onTick" or "onFinish"
TimerType timerType;
EventType(String eventType, TimerType timerType){
this.eventType = eventType;
this.timerType = timerType;
}
}
TimerType is an enum type:
public enum TimerType {
A,
B;
}
and create TimerA and TimerB classes extending CountDownTimer:
private class TimerA extends CountDownTimer {
final EventType onTickEvent = new EventType("onTick", TimerType.A);
final EventType onFinishEvent = new EventType("onFinish", TimerType.A);
#Override
public void onTick(long millisUntilFinished) {
notifyObservers(onTickEvent);
}
#Override
public void onFinish() {
notifyObservers(onFinishEvent)
}
}
The Observerwill receive the EventType instance via its update(Observable o, Object arg); in the arg argument
This question already has answers here:
Create a custom event in Java
(6 answers)
Closed 5 years ago.
I want to write a simple event handling solution in Java with custom events. I've only find GUI based examples, using ActionListeners so far. I've included a code, that I wrote in C#.
I want to create something like this in Java:
using System;
using System.Threading;
namespace EventHandlingPractice
{
class Program
{
static void Main(string[] args)
{
MusicServer mServer = new MusicServer();
Sub subber = new Sub();
mServer.SongPlayed += subber.SubHandlerMethod;
mServer.PlaySong();
Console.ReadKey();
}
}
// this class will notify any subscribers if the song was played
public class MusicServer
{
public event EventHandler SongPlayed;
public void PlaySong()
{
Console.WriteLine("The song is playing");
Thread.Sleep(5000);
OnSongPlayed();
}
protected virtual void OnSongPlayed()
{
if (SongPlayed != null)
SongPlayed(this, EventArgs.Empty);
}
}
// this class is class is the subscriber
public class Sub
{
public void SubHandlerMethod(object sender, EventArgs e)
{
Console.WriteLine("Notification from: " + sender.ToString() + " the song was played");
}
}
}
In Java you generally create an class for the event itself, extending from EventObject. The events of interest are defined in an interface ending with the name Listener, extending the interface EventListener.
The class which is able to broadcast events has a add/remove listener methods, where the interested party can register themselves.
Your code will work without following these conventions though, but they are (were?) meant for tools to understand names of the classes and methods.
Here a sample pseudo implementation for your domain:
public class Song {
}
public class SongEvent extends EventObject {
private final Song song;
public SongEvent(Object source, Song song) {
super(source);
this.song = Objects.requireNonNull(song);
}
public Song getSong() {
return song;
}
}
public interface SongListener extends EventListener {
default void songStarted(SongEvent event) { }
default void songPaused(SongEvent event) { }
}
public class SongServer {
private List<SongListener> listeners = new ArrayList<>();
public void addSongListener(SongListener listener) {
listeners.add(listener);
}
public void removeSongListener(SongListener listener) {
listeners.remove(listener);
}
public void playSong(Song song) {
// ....
SongEvent event = new SongEvent(this, song);
listeners.forEach(l -> l.songStarted(event));
}
}
public class MyEventHandler implements SongListener {
#Override
public void songStarted(SongEvent e) {
System.out.printf("Now listening to %s%n", e.getSong().getName());
}
}
In previous versions of Java it was standard to include an Adapter (SongAdapter) which would implement the listener interface as no-op operations. The reason for that was that if you would add events classes that extended from the adapter didn't need to add code. With Java 8 you can include default methods, so the Event Adapter pattern is not needed anymore.
I have used listeners with Android and never had any problems, however today when it tried to create a simple listener in Java I am getting NullPointerException, what is the cause of this and how can I fix it?
this includes 3 classes, ListenerMainStart.java, SendMessageClass.java, and ReceiveMessageClass.java
ListenerMainStart.java
public class ListenerMainStart {
public static void main(String[] args) {
new SendMessageClass();
}
}
SendMessageClass.java
public class SendMessageClass {
public OnStringRequestedListener onStringListener;
public Timer timer;
public SendMessageClass() {
timer = new Timer();
timer.schedule(new TimerAction(), 3000);
}
public void SetOnStringRequestedListener(OnStringRequestedListener listener) {
System.out.println("value of onStringListener " + onStringListener.toString());
onStringListener = listener;
}
public interface OnStringRequestedListener {
public void passString(String sendString);
}
public class TimerAction extends TimerTask {
#Override
public void run() {
if (onStringListener!=null){
// pass string to other class, ONSTRINGLISTENER IS ALWASY NULL
onStringListener.passString("string sent from SendMessageclass");
} else {
System.out.println("onStringListener is null");
}
}
}
}
ReceiveMessageClass.java
public class ReceiveMessageClass implements SendMessageClass.OnStringRequestedListener {
SendMessageClass senderClass;
public ReceiveMessageClass() {
// instantiate class
senderClass = new SendMessageClass();
// set the listener to the class
senderClass.SetOnStringRequestedListener(this);
}
#Override
public void passString(String sendString) {
// do action when string is sent from other class
System.out.println("message recevied from other class is " + sendString);
}
}
It looks like you need to call "SetOnStringRequestedListener" before you turn on your timers. As it is, that method never gets called and onStringListener never gets set. You do call that line of code in the receiver, but of course its far too late there. Your main should instantantiate both the receiver and the sender, SetOnStringRequestedListener, and then set off the timers.
SendMessageClass send = new SendMessageClass();
ReceiveMessageClass recv = new ReceiveMessageClass()
send.SetOnStringRequestedListener(recv)
EDIT: Then take out any code in the receiver that references the sender. The idea behind using the listener is that the two classes don't know directly about each other.
I'm new to Java and oriented-object and I'm trying to create a chat program. Here's what I'm trying to do:
Somewhere in my Main.java
Window window = new Window;
Somewhere in my Window.java
History history = new History()
Somewhere in my History.java:
public History()
{
super(new GridBagLayout());
historyArea = new JTextArea(15, 40);
historyArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(historyArea);
/* some other code... */
}
public void actionPerformed(ActionEvent event)
{
String text = entryArea.getText();
historyArea.append(text + newline);
entryArea.selectAll();
historyArea.setCaretPosition(historyArea.getDocument().getLength());
}
public JTextArea getHistoryArea()
{
return historyArea;
}
public void addToHistoryArea(String pStringToAdd)
{
historyArea.append(pStringToAdd + newline);
historyArea.setCaretPosition(historyArea.getDocument().getLength());
}
Now that I'm in Server.java, I want to use the method addToHistoryArea. How can I do that without making my historyArea static? Because if I understand well how static works, I couldn't have different historyArea even if I create a new History...
Thanks for your help and tell me if I got it all wrong!
In your Server constructor, send the instance of your History object (e.g new Server (history), and then you can invoke, history.addToHistoryArea, other option would be have a setter method which sets an instance of history to an instance variable, and then just call the addToHistoryArea method
public class Server{
private History history;
public Server(History history){
this.history = history;
}
public void someMethod(){
this.history.addToHistoryArea();
}
}
Another way
public class Server{
private History history;
public void setHistory(History history){
this.history = history;
}
public void someMethod(){
this.history.addToHistoryArea();
}
}
In someplace in Server you can have History
public class Server{
private History history;
public void setHistory(History history){
this.history= history;
}
public void someMethod(){
history.addToHistoryArea();
}
}
Or if you don't want to have an instance in Server
public void someMethod(History history){
history.addToHistoryArea();
}
Or if you want to be more decoupled you can take approach with the observer pattern or perhaps a mediator if they are colleagues.
You may want to create a History object in the Server class and then call the addToHistoryArea() method on that history instance.
public class Server{
private History history;
public void setHistory(History history){
this.history = history;
}
public void methodCall(){
history.addToHistoryArea();
}
}
I am currently implementing custom events and listeners according to the code posted below. I have been told that this is a very dirty implementation and that this needs to be changed. However, i am very new to java and android and do not see what is wrong with the current implementation. The way i have it below works and seems to be doing everything i needed it too. I was wondering if some people could please take a look at my code and make some suggestions on what i should change and what i am doing wrong. Taking my example and modifying it so that i can see what your talking about would be greatly appreciated.
Thanks in advance!
/* SmartApp.java */
public class SmartApp extends Activity
{
private ConnectDevice cD = new ConnectDevice();
private DataRobot dR = new DataRobot();
private DataBuilder dB = new DataBuilder();
private DataSender dS = new DataSender();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intro);
cD.addDataReceivedListener(new DataReceivedListener() {
#Override
public void dataReceivedReceived(DataReceivedEvent event) {
// TODO Auto-generated method stub
dR.analyzeData(event.getData());
}
});
dR.addDataAnalyzedListener(new DataAnalyzedListener() {
#Override
public void dataAnalyzedReceived(DataAnalyzedEvent event) {
// TODO Auto-generated method stub
dB.submitData(event.getData());
}
});
dB.addDataBuilderListener(new DataBuilderListener() {
#Override
public void dataBuilderReceived(DataBuilderEvent event) {
// TODO Auto-generated method stub
dS.sendData(event.getData());
}
});
}
}
/* ConnectDevice.java
* This class is implementing runnable because i have a thread running that is checking
* the contents of a socket. Irrelevant to events. */
public class ConnectDevice implements Runnable {
private List _listeners = new ArrayList();
private String data;
/* Constructor */
public ConnectDevice() {// does some socket stuff here, irrelevant to the events}
public void run() {// does some socket stuff here, irrelevant to the events}
public synchronized void addDataReceivedListener(DataReceivedListener listener) {
_listeners.add(listener);
}
public synchronized void removeDataReceivedListener(DataReceivedListener listener) {
_listeners.remove(listener);
}
private synchronized void fireDataReceivedEvent(String temp) {
DataReceivedEvent dRE = new DataReceivedEvent(this, temp);
Iterator listeners = _listeners.iterator();
while(listeners.hasNext()) {
((DataReceivedListener)listeners.next()).dataReceivedReceived(dRE);
}
}
public interface DataReceivedListener {
public void dataReceivedReceived(DataReceivedEvent event);
}
}
/* DataRobot.java */
public class DataRobot {
/* This class is for analyzing the data */
private List _listeners = new ArrayList();
private String data;
public boolean analyzeData(String temp) {
/* Analyze the data
* This function analyzes the data, as explained in the OP
* This function fires the analyzed data event when finished
* analyzing the data.
*/
data = temp;
fireDataAnalyzedEvent(data); // this fires the dataanalyzedevent
return true; //for now this will always return true
}
public synchronized void addDataAnalyzedListener(DataAnalyzedListener listener) {
_listeners.add(listener);
}
public synchronized void removeDataAnalyzedListener(DataAnalyzedListener listener) {
_listeners.remove(listener);
}
private synchronized void fireDataAnalyzedEvent(String temp) {
DataAnalyzedEvent dRE = new DataAnalyzedEvent(this, temp);
Iterator listeners = _listeners.iterator();
while(listeners.hasNext()) {
((DataAnalyzedListener)listeners.next()).dataAnalyzedReceived(dRE);
}
}
public interface DataAnalyzedListener {
public void dataAnalyzedReceived(DataAnalyzedEvent event);
}
}
/* DataBuilder.java */
public class DataBuilder {
private List _listeners = new ArrayList();
private String data;
public boolean submitData(String temp) {
/* Builds the data
* This function builds the data, as explained in the OP
* This function fires the databuilder data event when finished
* building the data.
*/
data = temp;
fireDataBuilderEvent(data); //firing the databuilder event when finished
return true;
}
public synchronized void addDataBuilderListener(DataBuilderListener listener) {
_listeners.add(listener);
}
public synchronized void removeDataBuilderListener(DataBuilderListener listener) {
_listeners.remove(listener);
}
private synchronized void fireDataBuilderEvent(String temp) {
DataBuilderEvent dRE = new DataBuilderEvent(this, temp);
Iterator listeners = _listeners.iterator();
while(listeners.hasNext()) {
((DataBuilderListener)listeners.next()).dataBuilderReceived(dRE);
}
}
public interface DataBuilderListener {
public void dataBuilderReceived(DataBuilderEvent event);
}
}
/* DataSender.java */
/* this class has no event, because it is done firing events at this point */
public class DataSender {
private String data;
public boolean sendData(String temp) {
data = temp;
return true;
}
}
Below here are the event objects for each event. I Have each of this defined in a separate file, not sure if that is good procedure or not.
/* DataReceivedEvent.java */
public class DataReceivedEvent extends EventObject{
private String data;
public DataReceivedEvent(Object source, String temp) {
super(source);
// TODO Auto-generated constructor stub
data = temp;
}
public String getData() {
// this function is just an accessor function
return data;
}
}
/* DataAnalyzedEvent.java */
public class DataAnalyzedEvent extends EventObject{
private String data;
public DataAnalyzedEvent(Object source, String temp) {
super(source);
// TODO Auto-generated constructor stub
data = temp;
}
public String getData() {
// this function is just an accessor function
return data;
}
}
/* DataBuilderEvent.java */
public class DataBuilderEvent extends EventObject {
private String data;
public DataBuilderEvent(Object source, String temp) {
super(source);
// TODO Auto-generated constructor stub
data = temp;
}
public String getData() {
// this function is just an accessor function
return data;
}
}
I would not say it is a "very dirty implementation". Using callbacks/observers/listeners is a good practice in my opinion.
When I write Android applications I like to layer it such that the "application" is plain old Java with no Android imports and could theoretically be used in a Swing app, a Java EE-based web site, etc. The "Android" part is strictly user interface.
What I use callbacks for is to allow the Android code to register interest in events that take place in the application. For example, in a Blackjack game, an Activity might call game.getDealer().playHand() to tell the application to perform the dealer hand play logic. As that logic executes in the application, events are fired like cardDrawn(card), cardFlipped(card), handTotalChanged(handTotal), etc. The Android part of the app listens to these and redraws things on the screen accordingly (but it knows nothing about Blackjack).
I actually just have my activities implement interfaces like CardListener, HandListener, etc. so they can receive the event directly (unlike how you do it), but your style isn't necessarily a bad way.
I agree with #SingleShot in theory, for the parts of your Android application that can be Android-agnostic, and so long as the overhead introduced by all the indirection layers does not slow the app down too much. IMHO, in many apps, there is relatively little that fits this description.
In another post, you proposed your above solution for one activity to communicate to another activity. In Android, activities aren't just some Java objects you can toss around willy-nilly. They are managed by the OS and have particular lifecycles. While the observer/observable pattern is quite delightful in some places, it is unsuitable where the observer/observable connection will create garbage collection problems. In particular, one activity cannot, and should not, be trying to hold some sort of listener interface on another activity.
Similarly, a clean observer/observable pattern may break down in the face of databases, threads, services, and other bits of Android reality.
So, in pure Java code, isolated from Android, what you have is probably OK. However, do not go around recommending it as solutions for Android-specific problems unless you know it will work for those Android-specific problems. And, when you start trying to make your code work in an Android app, please do not be shocked if you run into problems trying to make your textbook pattern implementation work within the constraints placed upon Android apps.