ViewFlipper, onClick events not delivered - android

I have my own implementation of the ViewFlipper (that exactly mocks the Android code, I wrote it before I realized this), the only difference being the fact that I hardcoded an inAnimation and an outAnimation in mine.
One side of the ViewFlipper has a 'flip' button which flips. The other side has a 'save' and 'cancel' button which flips it back. The 'save' performs a DB operation.
When the save or cancel, it flips the card correctly. If I perform the following operation: flip->cancel->flip->cancel..., it works fine. But when I perform: flip->save->flip, the last flip is non-response and logcat shows me that the touch operation was not delivered because of a timeout. The first thing I checked and ensured was that the database operation was not holding off the UI thread, and it was not!
I use the content of the ViewFlipper (using the View.getContent()) to perform DB operations, throw Toasts, build Alert Dialogs and the like. Might this create issues?
I've read a post somewhere saying that there was an issue with the ViewFlipper with animations and onClick() events not being delivered (the discussion ended with no solution). Am I a victim of this?

Try doing the save operation in a thread even though you are sure its not blocking the UI thread.
If that does not work, then set onTouch listener to the save view.

Related

Mocking presenter cause integration test to dump

Recently i've started covering my project with integration tests where mockito provides presenter instances to verify whether or not my views calling presenter methods properly during their events.
The issue was on the screen which has invisible ProgressBar and RecyclerView. Presenter of that screen have been loading data for that RecyclerView and controlling visibility of ProgressBar. When i replaced it with mock (used Mockito) it caused corresponding tests to totally stuck with error after a while:
Could not launch intent Intent { act=android.intent.action.MAIN flg=0x14000000
cmp=com.example.kinopoisk/com.example.mvp.view.activity.MainActivity } within 45 seconds.
Perhaps the main thread has not gone idle within a reasonable amount of time?
There could be an animation or something constantly repainting the screen.
Or the activity is doing network calls on creation? See the threaddump logs.
For your reference the last time the event queue was idle before your activity launch request
was 1476191336691 and now the last time the queue went idle was: 1476191336691.
If these numbers are the same your activity might be hogging the event queue
But activity was successfully running and was accessible for all user events like clicks etc.
How do you think, what cause a problem?
This is a question for community knowledge base only, i've found answer myself.
The explanation is in that line of error code: There could be an animation or something constantly repainting the screen.
When i had replaced presenter with mockito's one, it stopped controlling progress bar as well. The initial state of it was View.VISIBLE, so that was cause test to hadn't been able to connect.
The solution was just set initial state of ProgressBar to View.GONE, but found it was a bit of headache for me.

Is using runOnUiThread inside AsyncTask inefficient and bad?

I know it sounds crazy that someone is using runOnUiThread inside AsyncTask. Somehow, it is working for me but I wanna know if it is an acceptable and robust approach or not. Here is the scenario:
I have an app in which after successful login, user is rendered to next screen. In this new screen, 3 different methods are loading different types of data from a web server. These methods are:
getMembersForList() : It loads the list of community members and shows it in a listview.
getProfileData() : It loads the profile of logged in user and shows his name , image etc on the screen.
getNotificationCounts : It loads the count of new notifications for the user.
I applied 3 different approaches for it :
(1) Calling all 3 methods simply in onCreate i.e. no exclusive thread is being used for any of the methods . In this case , the transition from login screen to this screen becomes very slow and black screen shows up for some time before this activity shows up.
(2) Calling getMembersForList() on UI thread and the other 2 methods on exclusive threads. In this case transition becomes fast and list shows up quickly but Notification counts and username etc. don't show up because WrongThreadException occurs saying that this thread can't touch other thread's views (TextViews for username, notification count etc. which are declared globally) . The same thing happens when I start these threads from an AsyncTask as well.
(3) Calling getMembersForList() on UI thread and then starting an AsyncTask in which the other 2 methods are being called in "runOnUiThread" inside doInBackground() method. This solves both the above issues. Now the screen transition is faster and the WrongThread exception is also not occuring.
So far the approach-(3) is working good for me but I am not sure if this is the right way to do it because runOnUiThread and AsyncTask are 2 completely opposite things. Can anyone please clear my doubts about this scenario. Thanx in advance.
Yes, use-cases like this are a big reason why the runOnUiThread() method exists in the first place. The idea is you allow your background thread(s)/AsyncTask instance(s) to run your lengthy operations in the background, and then provide a simple hook that they can use to update the interface when they have the result (or at arbitrary intervals, as different pieces of the result become available).
As long as that's what you're doing, then your usage is fine. What you want to avoid doing is performing a lengthy operation on the main thread, either directly or indirectly by passing in some lengthy operation from a background thread.
Of course you don't have to do it that way if you don't want to. You could use postExecute() instead. Or you could store the result somewhere and then use any sort of message-passing API to notify the main thread that the result is ready, and so on.
I would advice to run all the 3 calls in the asyncTask, and update the UI in the postExecute() of the AsyncTask after the background taks is complete, postExecute runs on UIthread so you need not call anything explicit to run them on UIthread.

How to pause loop to wait for button press

I'm trying to create a turn based game using a 1v1 battle for android. My basic game loop checks if the two fighters are dead, if not then checks who is to go next. If its the player's turn then it should wait for an attack button to be clicked. If its the computer's turn, then it will execute a random attack. I'm having trouble getting the program to wait for the user input. I tried setting the button listener here but that's not doing it.
[edit] The determination for which character goes is based on a recovery integer. Each attack has a recovery value (50-100) which is added to the character's recovery. The nextMove() method checks to see which is closer to 0 and subtracts the difference from both characters. This allows the game to require more strategy because you don't attack just once a turn.
What can I do to get the game to pause at that point
Here's the code
public void battle(){
boolean playerGo;
while(!checkDead()){
playerGo=nextMove(); //returns true if its the players turn to go
if(playerGo){
//The game should wait here for the user input
moveButton1.setOnClickListener(this);
}
else{
randomMove(); //game automatically goes
}
}
}
When your app starts up, there's one thread on which everything runs, including event handlers. After you do your setup and call battle(), that thread is sitting there going around and around the loop. It's so busy going around and around the loop that it doesn't notice that there's a click event waiting to be processed!
There's a few options:
Restructure your code. It looks like the basic structure is that the player moves, then the game moves. You could remove this loop entirely, and instead call randomMove() after each time you handle the player's move. Handle the player's move in the OnClickListener for moveButton1. That way everything just happens on events. This would be simpler overall, and is probably the Right Thing to do.
Make the smallest possible change to your code to get it working. This would probably mean pulling the contents of your while loop into a Runnable, which you schedule by calling Handler.post. The first line calls checkDead and returns if true. The last line reschedules the Runnable. In between is the body of the while loop. The effect of this is that your loop body runs, then the event handler gets a turn, then your loop body runs, then the event handler runs. This is probably a bad idea.
Run battle() in another thread. This is probably a bad idea.
Why are 2. and 3. bad ideas? On a mobile device, battery life is precious, and running a check to see if you need to do something over and over again will keep the CPU busy chewing up battery life. Much better to sit there idle until you need to do something - this is what option 1 achieves.
So if 2. and 3. are bad ideas, why mention them? Welllllll, 2. I mention because it's the closest thing I've got to an answer to the question you actually asked. I mention 3. because there's a sense in which your current code is a fairly clear embodiment of the game logic. You could rework it so it runs in a separate thread, and instead of nextMove() returning true, nextMove() waits until the player makes a move (this would involve semaphores or mutexes or promises). But this would be an explicitly multi-threaded program, and as such would be difficult to write correctly. I recommend you don't attempt it at this stage in your programming career - the most likely outcome is a program that stops and waits forever, or that corrupts its data structures, in a way that is exceedingly difficult to diagnose.
Button.SetOnClickListener() function will be triggered, only when the user clicks on the button. As such it doesn't wait\block till the user input. This is by design in Android, that you cannot have a blocking window waiting for user input. Instead change your design to display hint saying 'now its user's move'.
User does first move by clicking the button.
SetOnclickListener() will be invoked. Have the user action code inside it.
Towards end of SetOnclickListener() have the computer action code.
With this cycle you can have user move and computer move chained.

Thread UI sleep withtout freezing scrollview

I'm trying to implements a game AI, and I got the following problem :
I'm calling a method from another class my UI Activity class, this method call itself some methods of the UI Activity class (to simulate click on screen among other things), and the things is, at the end of this method, I need to "pause" the game a few seconds to let the user see what did the AI.
So I tried running the method in another thread, but I got the error message providing from editing a widget from another thread. I tried to sleep the UI thread, but by doing that, the user can't use the scrollview anymore, and the changes aren't display before the sleep but after.
So I'd like to know how can I do this ?
(I've read some topics about AsyncTask, Handler, but can't make it work the way I need)
Thank's
You need runOnUiThread.
http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
http://steve.odyfamily.com/?p=12

ResourceNotFound on layout inflation

My app may launch a sub-activity for a specific purpose. When that activity finishes, I get the results in onActivityResult. These results are then processed in the subsequent onResume. This consists of a setContentView and also starting an AsyncTask that puts up a ProgressDialog.
This all works well when initiated the normal way, which is via a user request (i.e., menu selection) after the app is up and running. However, under some conditions I need to do this right as the app is starting up, so I initiate this sequence right from my onCreate. What then happens is that I get fatal ResourceNotFound errors within any o/s call that implicitly calls the layout inflater. I got around this with setContentView by pre-inflating the view in my onCreate method, but the AsyncTask's onPreExecute still fails on ProgressDialog.show() as it "fails to find" Android's own progress_dialog.xml!
Anyone know what's happening here?
I suspect it's something to do with the timing, where this is occurring before the main activity has even had a chance to display its screen. These calls are all being made on the main UI thread, but maybe something hasn't completed within the o/s under these conditions.
As a closeout, the problem turned out to be totally unrelated to what I described in my post. Turns out it was due to blindly using some code that had been posted in some online forum showing how to get and use AssetManager. Trouble is, at the end of the block of code he had put "assMan.close()". Well, this closes the asset manager for the entire activity and resources can no longer be accessed!
It took a while to find it since it was not something that I did via my own understanding.

Categories

Resources