AlertDialog in a Thread - java

I have a MainActivity Class and a Class that extends
public void run()
{
while(true)
{
this.person.movePerson();
checkWin();
checkHit();
this.gameview.postInvalidate();
try
{
sleep(4);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
This is my Thread. In The function 'CheckWin' the game need to check if the user won or not and then show a dialog.
But i can't show a dialog because of a handler problem.
so i tried to add a handler to the tread,
the problem that i always getting a syntax problems -- i am new to developing.
I passed a handler from the MainActivity, and tried to do this:
hand.post(new Runnable{
#Override
public void run()
{
while(true)
{
this.person.movePerson();
checkWin();
checkHit();
this.gameview.postInvalidate();
try
{
sleep(4);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}});
And everything that i get is only a syntax errors.
This is my AlertDialog Code:
AlertDialog.Builder alert = new AlertDialog.Builder(gameview.getContext());
alert.setTitle("Game Over");
alert.setMessage("Your Score is: " + result.score);
alert.setNeutralButton("Again!!", null);
alert.create();
alert.show();

I don't know what syntax error you get, but here is a little explanation on the working with threads in Android. First of all, if you are using plain Thread I suggest you to switch to HandlerThread. It's Android-specific Thread class built with Looper. Secondly, when you create a new Handler it will be attached to the thread from which it was created. If you are going to update UI, Handler which is responsible for posting UI updates to the MessageQueue should be created from UI thread. Alternatively you can pass a Thread-specific Looper to the Handler's constructor.
But I suppose you get syntax error on using this since it's pointing to a wrong object. If person and gameview are the fields of MainActivity class, for example, you can try to reference them by calling MainActivity.this.person...

Related

Java/Android - How to set timeout external service call with handler

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.

Removing location updates using a thread

I have a service that constantly polls a webservice for some options. These options basically restart a LocationManager. This restart is done using a custom event which gets fired from a method used inside a thread.
Here is my custom event
public class OptionsChangedEvent extends EventObject {
public OptionsChangedEvent(Object o){
super(o);
}
}
and the custom listener
public interface OptionsChangedListener extends EventListener {
public void optionsChanged(OptionsChangedEvent evt);
}
the thread that runs in the service and polls for new options is the following
private Thread optionsThread = new Thread() {
public void run() {
//Looper.prepare();
while(true) {
String opts = getOptsFromServer();
if(!opts.equals(currentOpts)) updateOpts(opts); //the prob is here
//Looper.loop();
Thread.sleep(10 * 1000) // sleep 10sec
}
}
}
Finally here is how I implement the listener inside my tracker.
locOpts.addOptionsChangedListener(new OptionsChangedListener() {
#Override
public void optionsChanged(OptionsChangedEvent event) {
Log.d("LOCATION_OPTIONS_CHANGED", "SUCCESS");
mLocationManager.removeUpdates(mLocationListener);
mLocationManager.requestLocationUpdates(
provider,
update,
0, mLocationListener
);
}
});
I had the following error which basically says that I need to use Looper.loop and Looper.prepare inside my thread.
12-03 11:31:39.544 26751-26843/com.test.location E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-10370
Process: com.test.location, PID: 26751
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:221)
at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:221)
at android.location.LocationManager.wrapListener(LocationManager.java:844)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:857)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:454)
at com.test.location.trackers.LocationTracker$2.optionsChanged(LocationTracker.java:93)
at com.test.location.options.LocationTrackerOptions.notifyListeners(LocationTrackerOptions.java:22)
at com.test.location.options.LocationTrackerOptions.fromJSON(LocationTrackerOptions.java:34)
at com.test.location.MainService$5.run(MainService.java:219)
If I uncomment the Looper parts the thread works only once and I cant figure out why this happens.
update
After some investigation I found that code that needs the message queue and creates this problem. Does anyone needed to do something like this? I would like to not change my design here if it possible.
private synchronized void notifyListeners(Object obj) {
for (OptionsChangedListener listener : listeners) {
listener.optionsChanged(new OptionsChangedEvent(obj));
}
}
Do you try to update the UI in your callback method updateOpts ?
Looper prepare & loop using in other way, in case when you want to send tasks from UI thread to the backround thread, so you send message to the thread, and inside the thread process that message in handlemessage event of Handler.
try to avoid UI calls directly from your thread, maybe also try using runOnUIThread(...)
or AsyncTasks onPost to make the proper callback to the UI thread.
The solution was actually very simple. I was missing the callback function.
locOpts.addOptionsChangedListener(new OptionsChangedListener() {
#Override
public void optionsChanged(OptionsChangedEvent event) {
Log.d("LOCATION_OPTIONS_CHANGED", "SUCCESS");
mLocationManager.removeUpdates(mLocationListener);
mLocationManager.requestLocationUpdates(
provider,
update,
0, mLocationListener,
Looper.getMainLooper() // this was the problem
);
}
});

Execute Listener in another thread

I'm trying to do something in android... something that I did before, but in other way. The target is to download a couple of images and then show it in the main thread ( yes, I mean synchronizing with a handler, asynctask or something like that, no problem. But... There's a problem to do that. Look at this snippet explaining what happens ( onAttach):
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d(MainActivity.TAG,"thread id on attach:" + Thread.currentThread().getId()); //it return thread ID:1
Runnable r = new Runnable(){
#Override
public void run() {
sQuery = new ServerQuery();
mQueue = Volley.newRequestQueue(getActivity());
Log.d(MainActivity.TAG,"inside runnable:" + Thread.currentThread().getId()); //it returns 2200 or something like that... it seems logic, another thread
mQueue.add(sQuery.getThumbs("1",
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(MainActivity.TAG,"inside listener:" + Thread.currentThread().getId()); //what?? returns thread 1! so i can't execute this on background... why it happens?
}
}));
}
};
Thread t = new Thread(r);
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
well, this just makes a thread and inside its thread defines a listener, but... Why does the listener is executed at the UI Thread? ( so, even if I use join(), the join() is just a test to debug, but the image gallery is created without the images downloaded, and I can't download nothing because is the main thread!)
And... What do you think about using a handler or something like this to synchonize it? or what would you use?
And if you create a new thread each time you enter in the listener?
Because who executes the listener is the caller of the listener.

Android :UI Thread Blocked

In my application I have created one customized dialog box ,which is showed in both webview and normal android application,and also I doing some background operation when the dialog box is showed, when ever I called the mydialog function it shows my customized dialog box and also it return some values,it is perfectly working when I use webview+javainterface but it doesn't work with ordinary applications, the flow is
first I will get my dialog, after I do some process(here the main thread will wait ,dialog need to show,) then I will return the string ,the problem is dialog doesn't show when I called this function instead of that the dialog will showed after my background process finished.
I call this my dialog box like:
String sample=mydialog();
public String mydialog() {
String mystring = null;
try {
myactivity.this.runOnUiThread(ShowDialog);
while (customizeddialog.Getvalue() == null) {
}
mystring = customizeddialog.Getvalue();
customizeddialog.Setvalue(null);
} catch (Exception e) {
return mystring;
}
private Runnable ShowDialog = new Runnable() {
public void run() {
try {
customizeddialog m_dialog = new customizeddialog(myactivity.this);
m_dialog.setCancelable(false);
m_dialog.show();
} catch (Exception e) {
}
}
};
When you enter the synchronized block in mydialog() you acquire this's lock. Inside this synchronized block, you run ShowDialog() on the UI thread, and try to acquire this's lock again when you enter the synchronized block in ShowDialog.
Since the lock has already been acquired, it will wait until it is released in mydialog(), which will never happen because ShowDialog never executes past synchronized(this). What you have is deadlock.

Waiting for a Runnable to complete before running another Runnable

I have an Android app with a main tab activity, and several activities within the individual tabs. In my main activity's onCreate(), I have a runnable that creates a list, and in the individual activities, I make use of this list.
In the individual activities's onCreate(), I also have Runnables that operate on the list. However, I need these Runnables to only run when the main tab activity's Runnable completes creating the list, otherwise I'd get a null list. I'm trying to find an elegant way of doing this. Right now, in my main activity's Runnable, I'm setting a global boolean variable isDone, and in my individual activity's Runnable, I'm waiting for isDone to be set via a while loop. This works, but probably isn't the best way of doing so.
Any thoughts?
Thanks.
Edit:
I'm trying the following code out, but I'm getting runtime errors:
In my MainActivity's Runnable:
mainRunnable = new Runnable() {
public void run() {
try {
generateList();
synchronized(this) {
listDone = true;
notifyAll();
}
} catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
}
};
Thread thread = new Thread(null, mainRunnable, "Background");
thread.start();
In my OtherActivity's Runnable:
otherRunnable = new Runnable() {
public void run() {
synchronized(MainActivity.mainRunnable) {
if (!MainActivity.getListDone()) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
}
};
Thread thread = new Thread(null, otherRunnable, "Background");
thread.start();
The mainRunnable seems to run completely, but the otherRunnable seems to cause the app to crash. I get the following error message:
01-10 15:41:25.543: E/WindowManager(7074): Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#40539850 that was originally added here
01-10 15:41:25.543: E/WindowManager(7074): android.view.WindowLeaked: Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#40539850 that was originally added here
You can use the wait and notify methods.
To do this, there needs to be some globally accessible object whose lock isn't used by anything else in the program at this point in time. I'm assuming that the list-creating Runnable itself can play this role.
So you could add something like this to the list-creating Runnable class:
private boolean listsDone = false;
boolean getListsDone() {
return listsDone;
}
And something like this to its run() method, immediately after it's done creating the lists:
synchronized (this) {
listsDone = true;
notifyAll();
}
And something like this to the other Runnables' run() methods, at the point where they need to wait:
synchronized (listCreatingRunnableObject) {
if (!listCreatingRunnableObject.getListsDone()) {
try {
listCreatingRunnableObject.wait();
} catch (InterruptedException e) {
// handle it somehow
}
}
}
Update: To clarify, both synchronized blocks need to be synchronized over the same object, and you have to call wait() and notifyAll() on that object. If the object is the Runnable, then it can be implicit for the first one (as in the above code), but if it's the activity, you need to explicitly use the activity object in both cases.
You can use a Queue like this:
public class RunQueue implemements Runnable
{
private List<Runnable> list = new ArrayList<Runnable>();
public void queue(Runnable task)
{
list.add(task);
}
public void run()
{
while(list.size() > 0)
{
Runnable task = list.get(0);
list.remove(0);
task.run();
}
}
}
This allows you to use one thread rather than multiple threads. And you can maintain all your existing "Runnable" objects while simultaneously cleaning up any code they have for waits and joins.
Set up a CountDownLatch with a value of 1 in the main thread, then have the dependent threads wait on it. When the main thread is done, you Count Down the latch to 0 and the waiters will start right up.
An active wait using a while loop is not a good idea at all. The simplest thing would be for the first Runnable to just fire up the rest of them as its last step. If that can't be made to work for some reason, take a look at posting a message to a Handler.
Is there a reason you are using Runnables and not Threads? If you use Threads, you can use the various thread communication primitives which exist for this exact reason (wait() and join() in particular).
I have created a helper method that contains all the boilerplate code for posting a runnable and waiting until it finishes running.
The logic is similar to what #Taymon describes, but the implementation is more general.
Check it out:
https://gist.github.com/Petrakeas/ce745536d8cbae0f0761
Maybe you can refer to Looper in Android. Simply, a thead keep running task from queue in a while loop.

Categories

Resources