I am currently working on an android app just for personal use. The app communicates with a server by TCP sockets. If the user makes an input it needs to be sent immediately. Also there can be messages from the server at any given time which need to be shown on the UI. For all the networking stuff I have a background thread in mind.
Since I need to pass messages From the UI to the networking thread at any user input and also messages from the networking thread to the UI at any given time my question follows: How can I pass the messages? I already read about the Handler class for 3hours and I couldn't figure out anything. How do handlers work? What would be a neat and smooth running implementation of that? I look more for a strategy to accomplish this goal, not necessarily implementation details.
Thank you so much in advance!
http://developer.android.com/reference/android/os/AsyncTask.html Use this I too had a lot of problems with handlers but the async task handles all that annoying work for you. Make sure you use onPrexecute() and onPostExecute() to update the UI. Hope this helps.
You can use AsyncTask in this case.
You can call it on the UI thread and in onPostExecute do what you want to do with the messages.
It is a much cleaner approach than doing all the dirty networking work there.
First, I'll say I'm learning this myself, but I've managed to get this exact setup working in a prototype. If anyone sees something that should be changed to work better in Android, by all means let me know.
Second, I'm using empty messages so that we have code that would actually work. I assume that creating message objects is straight forward enough.
Part 1 - UI to Network Thread
As far as I have seen, Handler is the answer you need, but it's not the whole picture. Deucalion's comment about Looper is where you need to look next.
http://developer.android.com/reference/android/os/Looper.html
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
This setup is counter intuitive at first, you need to create the Handler object between the Looper.prepare() and Looper.loop() calls, inside your run() method. I don't know the magic behind the scenes, haven't had a chance to get that far down the rabbit hole.
Important Note:
The sample shows an anonymous Handler() being created. I highly recommend subclassing Handler in your own class and then using an instance of that. It's just a matter of reusability, a lot of network code ends up being the same.
So, rename LooperThread to NetworkThread, or whatever you'd like it to be, and put your connection code in the run() method, but outside the Looper.prepare() / Looper.loop() block (again I don't know how the magic works, so I'm just assuming this is better to do than to have it inside).
// process incoming messages here
Tends to look like this:
switch(msg.what)
{
case 1:
break;
default:
break
}
The LooperThread example has public Handler mHandler; but I prefer to make the handler private and create a method to return it. I do this just to prevent the handler from being accessible until after the network connection is established. No connection, nothing to do with the messages.
So, somewhere in your activity code you create the NetworkThread object, run it, and then get the Handler from it.
NetworkThread network = new NetworkThread();
new Thread(network).run();
//Handler networkHandler = network.handler;
Handler networkHandler = network.getHandler();
Then you just send messages to that handler as needed.
networkHandler.sendEmptyMessage(1);
Part 2 - Network Thread to UI
There are a couple of different ways to handle this. You can create a handler inside the Activity class. All activities have a Looper already setup, so calling Looper.prepare and Looper.loop seem to cause problems.
In my code I create a handler in the onCreate() method, and then I pass it into my NetworkThread object. There may be better places to create this Handler, I don't know what will happen if your application is suspended and then started again later with onResume() or onRestart()
public NetworkThread(Handler mainHandler)
{
this.mainHandler = mainHandler;
}
Then anywhere else I need to send a message to the UI:
this.mainHandler.sendEmptyMessage(1);
I prefer this method because the Handler code, that does the actual work, either exists in the classes the actually respond to the message (using the anonymous Handler objects) or in Handler subclasses that may be in the same package.
You could also pass in the Activity or a View to the network thread and from that call runOnUIThread(Runnable), but that requires you pass in a Runnable. So the code that is meant to work on the UI is being written or referenced in the Networking classes.
Update
You could also use a Service for this. The method above works when the Activity and the Networking have the same life span. If we only need network connection while the Activity is active.
If you need network connectivity beyond the life of the Activity, in a music streaming app for example, then going with a Service would be a better choice. It didn't seem like this was specifically what you were looking for the question.
Related
I have old Android/java code, that contains two derives from IntentService,
and these services not run in separate processes.
The question is about the way to return result from these IntentService.
One service return result by using Handler + Runnable, to run code in main loop:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
MyApplication.get().setFoo(someThing);
}
});
the other one is uses LocalBroadcastManager.getInstance(this).sendBroadcast(in); to send message to Activity, and Activity subscribe via BroadcastReceiver on message in onResume, and unsubscribe in onPause.
Am I right, and in both case it is possible to use LiveData to simplify things?
IntentService should create LiveData and who want result should observe it,
and when new data arrives IntentService should call postValue,
or may be there are some reefs to prevent usage of LiveData here?
I think that LiveData will not help you in sending any data from Service to other components.
The problem with communication from any Service to other components is that you don't usually obtain a direct reference to the Service, therefore you can't directly "subscribe" to notifications.
Theoretically, if the Service runs in the same process, you can bind it, obtain a reference to Service object and then directly perform subscription. However, this is often an overkill and I don't see this pattern being used widely.
In your examples, there are two communication mechanisms:
Service reaches statically to Application object and sets some data. This is a communication through global state, and is generally considered an anti-pattern.
Communication through LocalBroadcastManager
From the above two mechanisms, I would use only #2 and avoid #1 at all costs.
Back to LiveData.
In order to be able to get LiveData object from the Service you will need to have a reference to that Service. This is usually impossible unless you bind Service in the same process, or use some ugly hack that involves global state.
Therefore, usefulness of LiveData in this context is very limited.
By the way, while LocalBroadcastManager is alright, I find this mechanism too complicated and restricting. Therefore, if the Service runs in the same process, I prefer to use EventBus in order to communicate from Service to other components (or vice-versa).
An example of such a communication you can see in SQLite benchmarking application that I wrote several days ago. In this app, TestService posts status changes and test results to EventBus as sticky events, and TestActivity subscribes to those events.
Both methods work with using LiveData since the purpose of LiveData is to have it on another thread and still notify users when something has changed. Seems like it would definitely replace LocalBroadcastManager.getInstance(this).sendBroadcast(in); and your IntentService would postValue. Just have your activity or anything that needs to be aware of the changes become an observer.
I have a java class buried deep in an SDK that performs an action and returns a boolean. It has no knowledge of the application's main activity, but I need the main activity to receive that boolean value.
I've seen a lot of questions regarding callbacks, broadcasts, and listeners but they all seem to have knowledge of the activity. My pojo does have an activityContext but I don't know how to get the value back to the application's main activity.
I'm already using an AsyncTask in my pojo and I'm trying to figure out how to send the boolean in the onPostExecute method in a way that the application's main activity can receive it.
Does anybody know how to do this?
I'd suggest using a message bus or observable/observer pattern.
Square has Otto a nice little open-source library that implements a message bus.
Observer pattern is well described at wikipedia for example.
Either way what you will have to do is essentially start listening to either your POJO if you make it Observable, or subscribe for bus events in onResume() (or onStart()) and stop listening in onPause() in your activity.
BUS
I like bus more because of it's loose coupling and the fact that you can send any arbitrary POJOs to the bus and only listen to one specific type for example.
so you post a message this:
bus.post(new SomethingICareAbout("I really really do"));
and elsewhere in your codebase (in your case in the activity):
#Subscribe
public void onSomethingIcareAbout(SomethingICareAbout thingsAndStuff) {
// TODO: React to the event somehow. Use what you received.
}
#Subscribe
public void onSomethingElseIcareAbout(SomethingElseICareAbout otherThings) {
// TODO: React to the event somehow. Use what you received.
}
The above is intentionally simplified, you still need to create the bus and subscribe to it, but you will find that in the docs :P
Also it uses annotations and is really lightweight (codewise).
Observer / Observable
Observer/Observable on the other had is part of Java, so it's built in. But it is tightly coupled, your activity will have to implement Observer, your POJO will implement Observable and you willl have to implement update() method in your Activity, this one will get all the updates no matter what you send by the Observable.
I hope this makes sense a bit :)
I want to write a class that handles all my network interaction called NetworkManager. So using an instance of this class I'd have something like:
NetworkManager nm = new NetworkManager();
...
nm.login(username, password);
...
However, what is the best approach so this network manager can do something on the UI thread once some response has been received? Modelling on a onClick style event I think this would be like:
nm.getPicture(new NetworkListener() {
#Override
public void run(Picture p){
updateUI(p);
}
Where I am unsure how to write the getPicture method and the NetworkListener() class.
I don't want to use AsyncTask, because this would mean I'd have to write the server code at different parts of the MainActivity. I have also considered a broadcaster and a listener, but this seems too much for a one off event.
Checkout Retrofit (http://square.github.io/retrofit/) it might be useful to consider for integrating the part of your network class. I'm not sure if you will have multiple similar calls, but if so, I would advice you to apply the Observer pattern, where you make the call and wait for the response asynchronously, yet, there's a nice library to accomplish that, very well documented, called Otto (http://square.github.io/otto/).
I have a client/server question that i am trying to figure out the best solution for.
If a client ever gets disconnected from the server, for any reason, i would like a way for the input output thread to alert the gui thread that something went wrong, and thus have the gui thread print an error and gracefully handle it (probably drop back out to the login gui). After the initial gui thread is created, the client could change to any number of guis, depending on what he is doing, so I am thinking i need a way to dynamically see what gui is currently being run.
The way that i was thinking of doing this so far:
1) Create an object that creates and shows every gui. So instead of calling invokeLater...SomeGui.CreateAndShoGui()... we would have this object be responsible for doing that, ie GuiObject.showSomeGui();
2) Have each gui implement an interface, which will insure there is a method that, when called, will gracefully shutdown this gui when we have lost connection to the server.
3) Have a thread that monitors the IO thread and the gui object. If something goes wrong on the IO thread, the IO thread will close down and notify the monitoring thread that we have lost connection the server. The monitoring thread could then alert any open guis (from the gui object) that we have lost connection and that it needs to shut down.
I have just started thinking about this, and so far this is the best solution i have come up with. Does this seem like a reasonable solution that wont add too much complexity to the code? Or can anyone recommend a solution that would be simpler for people reading the code to understand?
Thanks
EDIT:
The other option i am toying with is having an object on the IO thread, that also gets passed to each new gui as it is opened. This object will give the currently opened guis reference back to the io thread, so that the io thread can alert it if something goes wrong. I am leaning against this solution though, because it seems like it would be easier to read if you had one object that was dedicated to get this working (like the above solution), instead of passing some obscure object to each gui.
Let me just go through each of your ideas:
1) Bad idea - you are tying your whole application together through a single object. This makes maintainability difficult and is the antithesis of modularity.
2) This is the way to go IMHO. Since it seems that each gui has unique logic in a failure scenario then it stands to reason that the object that best understands what to do would be the gui object itself.
Another version of this idea would be to create an adapter for each gui to put this failure logic into. The advantage would be you have one less dependency between your application framework and your gui. The disadvantage is that this is an extra layer of complexity. If your gui is already pretty coupled to your application then I would choose the interface method. If you want to reuse your guis in another application then the adapter way could help facilitate that.
3) This complements #2 nicely. So let me get this straight - you would have 3 threads: the IO thread, the monitor thread, and the UI thread. I don't know if you need the monitor thread. From what you were saying the IO thread would be able to detect a connection problem by itself (probably because some form of IOException was caught). When a connection problem is discovered the IO thread is not busy since it is just going to shut itself down soon so it might as well just have the responsibility of notifying the guis that there was a problem. The guis should have their interface method called on the UI thread anyways so the IO thread is just calling a bunch of invokeLater() calls (or asyncExec() calls for SWT) and then the IO thread can just shut itself down.
4) (Your Edit) You are basically describing the Visitor pattern. I do not think this is a good solution because the call is from the IO thread to the gui and not the other way around. I am not sure how passing a visitor object around will help in this case.
One final thought. If you make your interface generic (not gui specific) then you can apply this pattern to other resources. For instance you may want to flush your user credentials when you lose connection (since you talked about going to the login screen again). That isn't really gui logic and should not be done from a gui class.
Edit: I would use an event model. Let's say you create a interface like this:
public interface ConnectionFailureListener {
void handleConnectionFailure(); // Add an event object if you need it
}
You could then have registration methods in some object (maybe the Runnable for the IO thread or somewhere else that is convenient for you). These methods would be pretty standard:
public void addConnectionFailureListener(ConnectionFailureListener l) {}
public void removeConnectionFailureListener(ConnectionFailureListener l) {}
When you show a gui on the screen you would add it to your registration object and when you close the gui you would remove it from the registration object. You can add other types of objects as needed - for example when you log in you can add a listener for your credential system and remove it again when log out is processed.
This way when you have a failure condition you simply loop through the currently registered listeners and the listener does its thing.
How would you go about implementing the equivellent of a wait until complete method call in Java?
Basically what I want to do is hava a method that sends a message over the network to a server application and waits till it gets the appropriate Ack message from the server with either an operation completed successfully or operation failed and an error message.
I already have a non blocking version of my method which passes a callback class in which has a method that is called on callback.
would it make sense to construct a callback class pass it in to my previous method and then perform a wait operation and on the callback have that class do a notify?
Adding a .wait() to your callback class would be the easiest path. It can sit there spinning on some flag until your callback switches it, just be sure to include Thread.yield() or .sleep() in your loop.
Saves having to rewrite an alternative blocking comms channel.
Short answer: Yes. I'm a fan of using what's in the class library already, what you describe sounds a lot like an Observer pattern, for which you have the Observer/Observable interfaces already, assuming you're using J2SE.
EDIT: Something was wrong with my coffee :) Obviously, what I meant to say was check out what's in java.util.concurrent package, specifically the Future<> and ExecutorService classes.
Yes, use your existing method like you are suggesting. Create the callback in your sync method call that will coordinate with the sync method call via wait()/notify(). The sync method will call the async one and then wait(). When the callback is called, it will call notify() to wake up the sync method so it can return the results.
Please ignore if you're not using JMS.
If you are using JMS, then you could use a QueueRequestor, which is an implementation of the Request Reply integration pattern.
That is, the following call appears synchronous to the client, even though asynchronous messages are used:
QueueRequestor requestor = null;
try {
requestor = new QueueRequestor(session, queue);
Message response = requestor.send(request);
} finally {
if (requestor == null) {
try {
requestor.close();
} catch (JMSException e) {
// log error message
}
}
}