I am quite new to Android and Java. Before I was working with C++ where the events where dispatched with messages. Now I would like to create the same user experience for Android platform and I would appreciate any of your suggestions or comments on what is the best way to bind events to user controls.
Here is an example from C++:
ON_MESSAGE(WM_RECORD_START, &CMainFrame::OnRecordStart)//Method OnRecordStarts() executes on WM_RECORD_START_MESSAGE
...
LRESULT CMainFrame::OnRecordStart(WPARAM wParam, LPARAM lParam)
{
m_pNetworkCtrl->SetGeoLocationInfo();
...
}
...
void CMainFrame::RecordStart()
{
PostMessage(WM_RECORD_START);
}
In the case above the method RecordStart() is bound to a Button (it is executed when a Button is pressed) and posts the message WM_RECORD_START. When the message WM_RECORD_START is received, the method OnRecordStart() is executed.
As mentioned before I would like to create a responsive user interface and am not sure if it would be good enough if the method OnRecordStart() is called directly from RecordStart():
void RecordStart()
{
OnRecordStart();
}
I would really appreciate any of your suggestions.
You can emulator the MFC style behavior in Android by using a Handler to post a Runnable into the message queue.
Here is a brief example
class MyClass
{
Handler m_myHandler;
Runnable m_myRunnable;
MyClass()
{
m_myHandler = new Handler();
m_myRunnable = new RUnnable()
{
public void run()
{
// do your stuff here
}
};
}
public void onclickListener(...)
{
// push the runnable into the message queue
m_myHandler.post(m_myRUnnable);
}
}
You have 2 questions here.
How to bind controls. I use
anonymous inner classes everywhere. It is a bit verbose to type in but auto completion makes it a snap.
how to make the UI responsive.
The key is not to do anything time
consuming in the UI thread. If it
takes more than .1s, do the work in
a worker thread and notify the UI to
update when the task is done. The
other thing is to make sure you
don't generate a lot of garbage
since the android GC is pretty primitive right now.
For Buttons I usually extend Button class and override onTouchEvent()
public boolean onTouchEvent (MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
setPressed(true);
}
return super.onTouchEvent(event);
}
Related
I have a plugin method that acts on remote hardware via Bluetooth.
It sends a command to the hardware, which executes some action.
After the hardware action finishes a callback defined outside of my method is called.
I only want to call CallbackContext.success(...) or CallbackContext.error(...) after the callback is called, so i want to wait for my callback to be called.
How would i go about this?
E.g. part of CordovaPlugin-class:
public void actOnHardware(CallbackContext callbackContext)
{
this.verifiyBluetoothEnabled();
this.hardwareConnection.doSomething()
// Now wait for the callback to complete before calling
// callbackContext.success() or error()
callbackContext.error("Not implemented.");
}
#Override
public void hardwareActionCallback(result)
{
// Notify actOnHardware() that we're finished.
}
This seems to be more of a Java thing, but i can't get my head to wrap around it.
Is using Object.wait() and Object.notify() a viable option or does calling wait() prevent the callback from getting called due to thread stuff? If so - how to solve this?
E.g. is it sufficient to just do:
private Object lockObj;
private boolean actionFinished;
public void actOnHardware(CallbackContext callbackContext)
{
this.verifiyBluetoothEnabled();
this.actionFinished = false;
this.hardwareConnection.doSomething()
while(!this.actionFinished)
this.lockObj.wait();
callbackContext.error("Not implemented.");
}
#Override
public void hardwareActionCallback(result)
{
this.actionFinished = true;
this.lockObj.notify();
}
Kind Regards
My scenario is an onCreate() activity method which executes the following code (simplified):
dialog.show(); //loading wheel
try {
remote.sendRequest(myData, new MyHandler());
}
catch (Exception e) {
dialog.dismiss();
//log and react
}
class MyHandler extends SDKSpecificCompiledHandler {
#Override
public void failure() {
dialog.dismiss();
//do stuff
}
#override
public void success() {
dialog.dismiss();
//do stuff
}
}
//I have read-only access to this handler!
public abstract class SDKSpecificCompiledHandler {
public abstract void success(JSONObject successData);
public abstract void failure(JSONObject errorData);
}
Explanation: A remote service is called passing an handler that gets called when he's done. A loading wheel (dialog) is shown to the user until a success, failure or exception happens.
The problem is when the service gets successfully called but no response ever comes. In that case dialog.dismiss() doesn't get called and the loading wheel keeps spinning for ever.
What I need is a sort of timeout which dismisses the dialog (and possibly takes other actions) after some seconds if the server doesn't get back.
My first though would be to create a new thread for the service call, and right after the launch set a timer which dismisses the dialog.
Would it be a good idea?
Thank you,
EDIT:
The service is third-party/not editable. I'm using a pre-compiled artifact.
Still not really sure what you're trying to achieve but if you want to run some code after some time on main thread (i.e. your code will do stuff to the UI), you can use a android.os.Handler
mHandler = new Handler(getMainLooper());
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
// do stuff on UI thread
}
},10000);
When your call returned from the server, simply cancel the messages on the queue:
mHandler.removeCallbacksAndMessages(null);
It is better to use time out in service call itself, You can set the time out with service , If you need know how to set the time out then I should know what kind of service you are using ?
One more thing is that if you are using a loader you should make that loader in such a way that it can be cancel by the client.
I first want to say I used google a lot to find a progress bar that fills itself when time passes. All results I found where either with a thread or with an Asynctask. As being new to Android, I thought it was easier to accomplish with an extra Handler that handles the updates of the progressbar.
However, I did not find anyone doing it my way. Does it maybe violate Android rules? For example, can I use multiple Handlers at the same time?
My code looks like:
public void restarttimebar()
{
stoptimebar();
for(int i=1;i<12;i++)
{
Message msg = timebarhandler.obtainMessage(0,i,0);
timebarhandler.sendMessageDelayed(msg, i*250);
}
};
public void stoptimebar()
{
timebarhandler.removeMessages(0);
Message msg = timebarhandler.obtainMessage(0,0,0);
timebarhandler.sendMessage(msg);
};
Handler timebarhandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
ProgressBar progressbar = (ProgressBar)findViewById(R.id.timebar);
if (msg.arg1 == 0)
{
progressbar.setProgress(0);
}
if (msg.arg1 > 0)
{
progressbar.setProgress(msg.arg1*9);
}
}
};
Now one can call restarttimebar(); to (re)start the progress bar. It will fill over 3 seconds with increments at each 0.25 second. Any remarks greatly appreciated!!
EDIT: Also added a stoptimebar(); to just stop the progressbar. Also, the standard size of a progressbar is 100. So I just make the twelve updates times 9. It is almost 100 ;) The bar does not have to be THAT very precise in my application.
As far as i know, the threads you create and Asynctasks (Non-UI-Threads) should not touch UI-stuff like your progressbar. If you need your task communicate with the progressbar, use Asynctask and make sure that UI related actions are done in onPostExecute(). This method will be also called by the main UI Thread.
I guess my method of updating the progress bar can be seen as correct. So for anyone who googles and has the same kind of question: Use the code in the question!
How to pass the message from working thread to GUI in java? I know in Android this can be achieved through handlers and Messages Class. But I want the same thing in Java can any one help me.
Thanks in advance.
Ranganath.tm
You must use SwingUtilities.invokeLater, because Swing components must only be accessed from the event dispatch thread.
The javadoc of this method has a link to the Swing tutorial about threads. Follow this link.
Here's an example:
public class SwingWithThread {
private JLabel label;
// ...
public void startBackgroundThread() {
Runnable r = new Runnable() {
#Override
public void run() {
try {
// simulate some background work
Thread.sleep(5000L);
}
catch (InterruptedException e) {
// ignore
}
// update the label IN THE EDT!
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setText("Background thread has stopped");
}
});
};
};
new Thread(r).start();
}
}
I think that the best way to do so is to use EventBus & MVP design for your GUI components. "Working thread" fires event by sending it to bus, and Presenters which are handlers for particular type of event, are notified about it.
Nice description of such design can be found here:
Is there a recommended way to use the Observer pattern in MVP using GWT?
...although question is about GWT answer is applicable to all applications designed according to MVP.
Send events. See this tutorial
We do it like this on FrostWire, through this utility function we can check if the runnable/thread you're using is being invoked already from the GUI thread
/**
* InvokesLater if not already in the dispatch thread.
*/
public static void safeInvokeLater(Runnable runnable) {
if (EventQueue.isDispatchThread()) {
runnable.run();
} else {
SwingUtilities.invokeLater(runnable);
}
}
You can use SwingWorker class, its designed to address this case:
http://download.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
I use some menuitems in my application and I have a question about the run method which I override.
private MenuItem menuItemUpdate = new MenuItem("Update", 0, 0) {
public void run() {
// Can I write GUI code here?
}
};
As the comment states, can I write GUI code here? I can`t right? Since I am not on the GUI thread? Should I use the invokeLater-method when I have code that changes the GUI? And what about Dialogs, should they be invoked in invokeLater-methods as well?
And is it necassary to override the run-method of MenuItem if I have made another thread which will be invoked when the user selects the menu item? Could I start that thread in the constructor instead? And leave the run method un-overridden?
You can write UI code there, because the UI thread handles the user's actions, and calls the menu item code. All user interaction is handled by the UI thread.
Yes, you can - because it's on the UI thread, for example:
private MenuItem menuItemUpdate = new MenuItem("Update", 0, 0) {
public void run() {
Show.status("Huzzah!");
}
};
And it seems to be general rule that you don't add any locking around - until you get an IllegalStateException ;-)