I been inspired by Signals events pattern in AS3, that replace the native events of flash. And it's work much better, both in performance and readability.
So I am trying to implement it in Java.
the main Idea of this pattern is that you are working with objects instead of types, saving by this the time to find the "Dispatcher" class to handle your event dispatch.(Dispatching event is sending event to all the listeners)
So lets jump into the code:
In this sample I will create AlarmManager and handle his alarm event.
First we need to create our Interface for this event
public interface IAlarmEvent {
void alarmEventHandler(String alert);
}
Now the event itself:
public class AlarmEvent extends Signal<IAlarmEvent> implements IAlarmEvent {
public void alarmEventHandler(String alert) {
dispatch("alarmEventHandler", alert);
}
}
And here is the AlarmManger:
public class AlarmManager {
public final AlarmEvent alarmEvent = new AlarmEvent();
public void init(){
// Dispatching the event
alarmEvent.alarmEventHandler("Wake up");
}
}
Here is an Activity who is listening for this event:
public class MainActivity extends Activity implements IAlarmEvent{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AlarmManager alarmManager = new AlarmManager();
alarmManager.alarmEvent.addListener(this);
alarmManager.init();
}
public void alarmEventHandler(String alert) {
Log.d("MyLog", "Event : " + alert);
}
}
And here is how I wrote the Signal class
public abstract class Signal<T> {
private LinkedHashMap<T, T> listeners = new LinkedHashMap<T, T>();
protected void dispatch(String methodName, Object...arguments){
Set<T> keySet = listeners.keySet();
if(keySet.size() == 0){
return;
}
Iterator<T> iterator = keySet.iterator();
Method method = null;
do{
T listener = iterator.next();
if(method == null){
try {
Class<?>[] classes = new Class<?>[arguments.length];
for(int i = 0; i < arguments.length; i++){
classes[i] = arguments[i].getClass();
}
method = listener.getClass().getMethod(methodName, classes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
try {
method.invoke(listener, arguments);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}while(iterator.hasNext());
}
public void addListener(T listener) {
listeners.put(listener, listener);
}
public void removeListener(T listener) {
listeners.remove(listener);
}
}
This pattern is:
fast - no need to search for type and trigger the eventDispatcher, it's done immediately.
have great readability - Just by looking at the class you know exactly what events he dispatch, and how each event looks like.
However it's not working well. If I am using primitives for my interface, the Signal fails to find the Method and invoke it. And I don't like the idea passing the Method name to the signal. Any Ideas how to improve this? And what do you think about this pattern?
Seems like this pattern is already implemented in these classes
java.util.Observable
java.util.Observer
Related
I have several activities and one asyncTask that uses the same interface for callback methods as below
The interface used by all
public interface AsyncTaskCallback {
void onCookie(CookieManager cookieManager);
void onResponse(String response);
void onProgress(String... values);
void onError(Exception e);
}
AsyncTask1 is called from all activities as follows
public void exec_taskt() {
alertDialog.SetText("Sending Request...");
AsyncTask1 task1 = new AsyncTask1("https://stackoverflow.com");
task1.setCookieManager(cookiejar);
task1.setCallback(this);
task1.execute();
}
Each Activity also implements the interface
#Override
public void onCookie(CookieManager cookieManager) {
cookiejar = cookieManager;
}
#Override
public void onResponse(String response) {
try {
PostProc(response);
}catch (Exception e){ // ERROR HERE
e.printStackTrace();
}
}
#Override
public void onProgress(String... values) {
alertDialog.SetText(values[0]);
}
#Override
public void onError(Exception e) {
///SAME ERROR HERE TOO
//Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
swipeRefreshLayout.setRefreshing(false);
}
private void PostProc(String response) {
//the response string is parsed and displayed in a recyclerview in this method
//this method is slightly different for each activity
}
AsyncTask1
public class AsyncTask1 extends AsyncTask<String, String, String> {
private String address = "";
private CookieManager mCookieManager;
private Exception mException;
private AsyncTaskCallback mCallback;
public AsyncTask1 (String page) {
this.address = page;
}
public void setCookieManager(CookieManager cm) {
this.mCookieManager = cm;
}
public void setCallback(AsyncTaskCallback cb) {
this.mCallback = (AsyncTaskCallback) cb;
}
#Override
protected String doInBackground(String... strings) {
try{
//all code here is executed without error
//code skipped for simplicity
// basically just loads the given url and then...
publishProgress("Page Loaded");
mCallback.onCookie(mCookieManager);
mCallback.onResponse(response);
return response;
} catch (Exception e) {
publishProgress("Error");
e.printStackTrace();
mCallback.onError(e);
return "";
}
#Override
protected void onProgressUpdate(String... values) {
Log.d(tag, TextUtils.join(",", values));
mCallback.onProgress(values);
super.onProgressUpdate(values);
}
}
The errors I get are marked
ERROR HERE
in the code above. and the message is as follows
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
My main suspect is the PostProc() method in the activity that does play with the UI component. But doesnt implementing the interface in the activity mean that part of the code runs in the main UI thread? I know you can pass the activity instance to the asyncTask and call the PostProc() method from postexecute of the asyncTask but I would like to explore an alternative way to it, since the same asynctask is accessed by other activities as well. the returns are the same for all activities. Only the PostProc Method is different.
Thanks in advance
Instead of using callback interface you can use a android.os.Handler() which is associated with the Looper.getMainLooper() to update the views like:-
AsyncTask1 task1 = new AsyncTask1(android.os.Handler(Looper.getMainLooper(), msg -> {
// handle message sent from asyncTask
return false;
}), url);
Then in task1 send the message using using the handler
public AsyncTask1 (Handler handler, String page) {
this.address = page;
this.handler = handler;
}
then ,
Message message = new Message();
message.obj = uiData;
handler.sendMessage(message);
The handler onHandleMessage will always execute on the main looper !
I'm trying to do a setText() on a Textview (already instantiate in the onCreate()) called by a Handler and using the ruiOnUiTread() but I have a nullPointerException on the Textview.
Where can the problem come from?
I saw in the debug that the instance of the activity was not the same between the instantiation and the setText() while I do not change activity but impossible to instantiate it in the same place as the setText().
private TextView ambianceTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ambianceTextView = findViewById(R.id.valeur_ambiance);
StarterKillerPidroid.getInstance().startApp();
}
private final Runnable retrieveData = new Runnable() {
public void run() {
try {
setText();
} catch (Exception e) {
e.printStackTrace();
}
handlerRecup.postDelayed(retrieveData, 1000);
}
};
public void setText(){
runOnUiThread(new Runnable() {
#Override
public void run() {
ambianceTextView.setText("test");
}
});
}
public void doAfterLogin() {
handlerRecup.postDelayed(retrieveData, 10000);
}
the runnable is started by a function called by a callback of an http request with Volley
public class StarterKillerPidroid {
void startApp() {
//Sending a request
PostmanPidroid.getInstance().login();
}
public void ackLogin(Boolean isValid) {
if (isValid) {
ActivityMain.getInstance().doAfterLogin();
} else {
PostmanPidroid.getInstance().login();
}
}
}
The class Postman :
public class Postman {
public void login(){
// Parameters
String email = "test#tes";
String password = "test";
// Encoding the request with parameters
JsonObjectRequest request = EncoderDecoderPidroid.getInstance()
.encodeRequestLogin(email, password);
// Sending the request
sendRequest(request);
}
void sendRequest(StringRequest message){
// Creating the queu if it's not create
if (queue == null) {
queue = Volley.newRequestQueue(context);
}
// Adding the request to the queue
queue.add(message);
}
}
When a success response is received, this callback is called :
private Response.Listener<JSONObject> callbackLogin =
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
...
StarterKillerPidroid.getInstance().ackLogin(true);
}
};
Basically, this kind of problem is due to the instance. It may be possible that your textview instance is not initialized. One more thing using handler directly for updating UI thread is not a good idea. Instead of directly updating Ui with handler you should use FunctionalInterface for doing this.
FunctionalInterface is a good approach for such cases.
A functional interface is an interface that contains only one abstract method. They can have only one functionality to exhibit. From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface. ... Runnable, ActionListener, Comparable are some of the examples of functional interfaces.
Java has a predefined FunctionalInterface Callable. It goes something like this
public static void doDid(final Callable<Void> callable) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
try {
callable.call();
handler.postDelayed(this, every * repeattime);
} catch (Exception e) {
e.printStackTrace();
}
}
}, every * tempvalue);
}
and use this for updating UI in this way
doDid(new Callable<Void>() {
#Override
public Void call() {
textView.setText("Your text");
return null;
}
});
There is one open-source library available for Android which works like a charm is such cases called Predictor. You can download it from here and import in your project. You can also contribute in this project for saving many developers life.
Do you wanna see how predictor can do this?
Predictor.every(3).second().doDid(new Job<Void>() {
#Override
public Void run() {
textView.setText("Your text");
return null;
}
});
What can you do with predictor?
Predictor gives you several ways of handling multithreading some of them are as follows:
Predictor.every(3).second().doDid(something());
Predictor.every(5).minutes().doDid(something());
Predictor.every().hour().doDid(something());
Predictor.every().week().doDid(something());
Predictor.every().month().doDid(something());
and many more...
Try this way:
private final Runnable retrieveData = new Runnable() {
public void run() {
try {
ambianceTextView = (TextView) findViewById(R.id.valeur_ambiance);
setText();
} catch (Exception e) {
e.printStackTrace();
}
handlerRecup.postDelayed(retrieveData, 1000);
}
};
apologies for the basic question; I'm new to the Java world and the spring framework. I've built a little example application that makes a bunch of async requests to an external service and returns a list of the responses ('metrics'), but I need to make my application wait until all the responses have come back. Right now I have a (don't hate me) Thread.sleep while I let the results come back, but obviously this is very nasty. Can anyone suggest a better way of architecting this?
Calling class:
#Service
public class MetricService {
#Autowired
private MetricProcessor processor;
private LinkedBlockingQueue<Metric> queue;
#Scheduled(fixedDelay = 60000)
public void queryExternalService() {
List<Metrics> metrics = new ArrayList<>();
metrics = processor.getMetrics();
//this is horrible and I'm a horrible human being
try {
Thread.sleep(10000); //wait for the requests to come back
}
catch (Exception e) {
e.printStackTrace();
}
queue.addAll(metrics);
}
}
Class:
#Component
public class MetricProcessor {
#Autowired
private AsyncClient externalClient;
public List<Metrics> getMetrics() {
List<Metrics> returnObj = new Arraylist<>();
for(Blah blah : bleh) {
Request request = new Request("abc");
externalClient.getMetricAsync(request, new AsyncHandler<request, result>() {
#Override
public void onError(Exception e) {
System.out.println("Error");
}
#Override
public void onSuccess(Request request, Result result) {
returnObj.add(new Metric(result.getKey(), result.getValue()));
}
});
}
return returnObj;
}
}
Any help would be greatly appreciated!
Try a Future.
In MetricService:
public void queryExternalService() {
Future<List<Metrics>> metricsFuture = processor.getMetrics();
try {
queue.addAll(metricsFuture.get(60, TimeUnit.SECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
So notice instead of the desired List, your processor provides a reference to a Future which may fulfil that request later:
public Future<List<Metrics>> getMetrics() {
MetricsFuture metricsFuture = new MetricsFuture();
// Need to ask for the metrics to be built
metricsFuture.buildMetrics();
return metricsFuture;
}
private static class MetricsFuture extends AbstractFuture<List<Metrics>> {
// Assuming the requests are asynchronous, this should be a thread-safe list
List<Metrics> returnObj = new CopyOnWriteArrayList<>();
void buildMetrics() {
for(Blah blah : bleh) {
final Request request = new Request("abc");
externalClient.getMetricAsync(request, new AsyncHandler<request, result>() {
#Override
public void onError(Exception e) {
onError(request, e);
}
#Override
public void onSuccess(Request request, Result result) {
addMetrics(new Metrics(result.getKey(), result.getValue()));
}
});
}
}
void onError(Request request, Exception e) {
// Is any error a total failure? This allows us to terminate waiting
setException(e); // alternative we could remove request or keep a list of errors
System.out.println("Error");
}
void addMetrics(Metrics metric) {
returnObj.add(metric);
// Once we have received the expected number of results we can pass that prepare that
// as a result of this future.
if(returnObj.size() == bleh.size()) {
set(returnObj);
}
}
}
I'm writing an Android messaging application, and 1 class is calling another class, and I wish for the calling class to wait for the callee class to complete before carrying on.
Caller Class (MessageManagement) code snippet is as follows:
private static Messenger myMessenger;
try {
Message msg = Message.obtain();
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
myMessenger.send(msg);
Log.d(TAG, "Sent");
} catch (Exception e) {
e.printStackTrace();
}
// Wait here until myMessenger completes its task
doOtherStuff();
Right now, doOtherStuff() starts and finishes before myMessenger starts. I need myMessenger to complete before doOtherStuff() starts.
I've read about wait() and notify() but I'm not sure how to implement it here, or whether it's the right choice.
Some background about the flow of the program. It's basically a messaging app that I inherited, so I'm not exactly sure of its framework. From what I can tell tracing the flow of the code:
When an SMS message is received, the SMS receiver BroadcastReceiver(SmsReceiver) handles it, getting the sender address and message body, then calling a SMS handler service(HandleSmsService), which then calls the caller class in a runnable with the following code:
HandleSmsService
public class HandleSmsService extends Service {
private String message;
private MessageManagement messageManager;
private Handler timeoutHandler = new Handler();
#Override
public void onStart(Intent intent, intent startid) {
message = intent.getExtras().getString("message");
messageManager = new MessageManagement(this);
timeoutHandler.postDelayed(runnable, 10);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
try {
messageManager.handleMessage(message);
stopSelf();
} catch (Exception e) {
e.printStackTrace();
}
}
};
MessageManagement is my caller class, and MessageManagement.handleMessage() is the top most code snippet presented earlier.
The MessageManagement.handleMessage() apparently calls another Handler in the callee class when it calls myMessenger.send(msg). This Handler code is as follows:
private Handler smsHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// do some stuff
}
};
I'm assuming the posted code is running on the MainThread and the reason why you are using a handler is that something asynchronous is done on another thread when receiving that message.
In that case, you can't use wait on the thread, as it will lock up the UI and probably cause an application not responding error.
Without changing too much of your code, one way to do it is to nest a listener in your constructedMessage for e.g.
public class DoStuffRequest {
private OnFinishListener mOnFinishListener;
private boolean isCanceled;
private String mMessage;
public interface OnFinishListener {
public void onFinish();
}
public DoStuffRequest(String message) {
mMessage = message;
}
public OnFinishListener getOnFinishListener() {
return mOnFinishListener;
}
public void setOnFinishListener(OnFinishListener onFinishListener) {
mOnFinishListener = onFinishListener;
}
public void cancel() {
isCanceled = true;
}
public void notifyFinish() {
if (!isCanceled && mOnFinishListener != null) {
mOnFinishListener.onFinish();
}
}
public String getMessage() {
return mMessage;
}
}
then use some along the line of this to get the ball rolling:
private static Messenger myMessenger;
private DoStuffRequest mRequest;
...
private void send(String message) {
mRequest = new DoStuffRequest(message);
mRequest.setOnFinishListener(new ConstructedMessage.OnFinishListener() {
#Override
public void onFinish() {
doOtherStuff();
}
});
try {
Message msg = Message.obtain();
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
myMessenger.send(msg);
Log.d(TAG, "Sent");
} catch (Exception e) {
e.printStackTrace();
}
}
private void doThisIfYouWantToCancel() {
if (mRequest != null) {
mRequest.cancel();
}
}
your Handler/Service code can now call constructedMessage.finish() when the async stuff is done. Depending on what doOtherStuff() does (e.g. when manipulating the UI), you might want to do this on the MainThread (the code i've written above is NOT thread safe and i assume you are calling the listener on the MainThread).
Also remember to call constructedMessage.cancel() in case you do not want to get notified any more (e.g. you are leaving the activity/fragment).
this is just one way to do it, depending on your needs, some other methods might be a better choice.
I guess it should look something like this:
try {
Message msg = Message.obtain(handler, new Runnable() {
#Override
public void run() {
doOtherStuff();
}
});
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
msg.sendToTarget();
Log.d(TAG, "Sent");
} catch (Exception e) {
e.printStackTrace();
}
The other way to do this using native means:
private static Messenger myMessenger = new Messenger(new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
// do something what you need
if (msg.getTarget() != null) {
msg.sendToTarget();
}
return false;
}
}));
try {
final Message msg = Message.obtain();
msg.setTarget(new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
doOtherStuff();
return false;
}
}));
msg.arg1 = constructedMessage.length();
msg.arg2 = -1;
msg.obj = constructedMessage;
Log.d(TAG, "Calling myMessenger.send()");
myMessenger.send(msg);
Log.d(TAG, "Sent");
} catch (final Exception e) {
e.printStackTrace();
}
I am writing code that communicates on serially with several machines. Each machine interacts with an instance of a communicator class and that class has a serial port event listener.
When the machine recieves enough data it peforms a test that is quadratic. (cant be helped as the test itself is quadratic) and the input can be large. As a result I am afraid that some of the serial events wont be registered if the code is doing the calculation.
As a solution I considered creating a Thread that runs the calculation and setting it to sleep during its loop for a time determined by the number of machines connected. However I then thought that maybe it would be a better idea if I could put that Thread asleep from the serialevent method? is this possible or will the thread not run until the method that is running finishes?
Now in the code below I have included the Thread.sleep within the Calculations method as this is what I was going to do if the serialevent cant interupt the thread
private class CalculationThread implements Runnable{
#Override
public void run()
{
calculateResult();
}
}}
private void calculateResult() {
ArrayList<Double> theoretical_vals;
ArrayList<ArrayList<Double>> theoretical_curves = new ArrayList();
double current_maxdiff, maxdiff;
double ao = measurements.get(0).getMeasurement();
theoretical_vals = RadioCalculations.theoreticalVals(measurements, hf, ao);
theoretical_curves.add(theoretical_vals);
int index = 1;
for (MeasurePoint m : measurements) {
theoretical_vals = RadioCalculations.calibratecontrolValues(measurements, index, hf);
try {
Thread.sleep(20*(parent.getNumberOfTests()-1));}
catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
theoretical_curves.add(theoretical_vals);
index++;
}
index = 1;
maxdiff = 0;
for (ArrayList a : theoretical_curves) {
try {
Thread.sleep(20*(parent.getNumberOfTests()-1));
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
current_maxdiff = compareValues(a, measurements);
if (current_maxdiff > maxdiff) {
if (current_maxdiff > pass_limit) {
passed = false;
failed_measurementpoint = index;
break;
}
maxdiff = current_maxdiff;
index++;
}
}
passed = true;
max_dev = maxdiff;
logResults();
}
public void serialEvent(SerialPortEvent spe) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
pauseListen(false);
if (spe.getEventType()== SerialPortEvent.DATA_AVAILABLE){
try {
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);}}
catch (IOException e) {e.printStackTrace();}
input_line= new String(readBuffer,0,numBytes);
input_line = input_line.replaceAll("[\n\r]","*");
buffer.append(input_line);
if (input_line.contains("*")){
input_line= buffer.toString();
input_line = input_line.replaceAll("[*]","");
buffer.setLength(0);
pauseListen(true);
update(input_line);}}
}
}
You could use a BlockingQueue (since Java 5) for put the new calculations in this queue while there is one calculation in process.
First, you need a wrapper class for you received data of the serial port:
class CalculationWrapper {
// fields
// getters setters
public void calculateResult() {
// operations
}
}
The method calculateResult for do the calculations can be in this class or in the next class:
class Calculator implements Runnable {
private final BlockingQueue<CalculationWrapper> queue;
Calculator(BlockingQueue<CalculationWrapper> q) {
queue = q;
}
public void run() {
try {
while (true) {
CalculationWrapper wrapper = queue.take();
wrapper.calculateResult();
}
} catch (InterruptedException ex) {
// log error
}
}
}
The method take wait until there is more new calculations in the queue.
The class for the listener of events of serial port (and for put the new calculations) could be:
class Receiver implements Runnable, SerialPortEventListener {
private final BlockingQueue<CalculationWrapper> queue;
Receiver(BlockingQueue q) {
queue = q;
}
public void run() {
try {
while (true) {
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
// log
}
}
public void serialEvent(SerialPortEvent evt) {
switch (evt.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
try {
// read
CalculationWrapper wrapper = new CalculationWrapper();
// set data on wrapper
queue.put(wrapper);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
And the setup class o main class:
class Setup {
public static void main(String args[]) {
// get port
// register listener
BlockingQueue q = new ArrayBlockingQueue(10);
Receiver p = new Receiver(q);
Calculator c1 = new Calculator(q);
new Thread(p).start();
new Thread(c1).start();
}
}
This in one way. See more:
Lesson: Concurrency (The Java Tutorials > Essential Classes)
SerialPort example « javax.comm « Java by API
The Java Communications API: A Working Example - By Rick Proctor