switching xml layout causes crash in Android - android

I need to write an android application like a book. I have approximately 100 images and i need to show them with back, forward and another buttons.
I tried to create an xml-layout for each image and made images to layout's background.
While running application, if i press buttons fast, program crashes during switching xml-layout.. If i decrease image sizes my problem decreases also. Unfortunately, i need another solution in order to solve it because i cannot use smaller image-size but i have crash problem still.

Have one layout, with an ImageView in it. Then keep changing the source image for the image view whenever you need to cycle to the next or previous image.

Part of the problem is that clicking a UI button returns immediately / queues clicks, even though the action associated with that click has not yet completed. For reasons beyond the scope of this response, its worth noting that simply deactivating the button while "doing work" is ineffective. There are a couple solutions to this kind of problem: One is to use a boolean flag that gets set only after the underlying "work" has completed. Then within the button action handler, you ignore button clicks that occur before the flag is reset:
/**
* Button presses are ignored unless idle.
*/
private void onMyButtonClicked() {
if(idle) {
doWork();
}
}
/**
* Does some work and then restores idle state when finished.
*/
private void doWork() {
idle = false;
// maybe you spin off a worker thread or something else.
// the important thing is that either in that thread's run() or maybe just in the body of
// this doWork() method, you:
idle = true;
}
Another generic option is to filter using time; ie. you set a limit where the max frequency of button presses is 1hz:
/**
* Determines whether or not a button press should be acted upon. Note that this method
* can be used within any interactive widget's onAction method, not just buttons. This kind of
* filtering is necessary due to the way that Android caches button clicks before processing them.
* See http://code.google.com/p/android/issues/detail?id=20073
* #param timestamp timestamp of the button press in question
* #return True if the timing of this button press falls within the specified threshold
*/
public static synchronized boolean validateButtonPress(long timestamp) {
long delta = timestamp - lastButtonPress;
lastButtonPress = timestamp;
return delta > BUTTON_PRESS_THRESHOLD_MS;
}
Then you'd do something like this:
private void onMyButtonClicked() {
if(validateButtonPress(System.currentTimeMillis())) {
doWork();
}
}
This last solution is admittedly non deterministic, but if you consider that users almost never intentionally click button more than 1-2 times a second on a mobile device, its not so bad.

Related

Card guessing game, second card won't draw mid thread

mid project here and looking for a quick and dirty way out of a sticky situation.
The game looks like this. To play, click a card, and click another, and if they match they both stay shown. Match all and game is over.
In my case, when I have one card shown, when the user selects the second card, the processing logic, should set the card to be visible AND ONLY THEN, check if there is a match. And if not, return the card back to the old image.
This code, I hope, helps you understand what I'm trying to do.
gridLayout.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//HOW DO I FORCE THE INTERFACE TO REDRAW BEFORE CONTINUING THE THREAD?
engine.setCardStateToShow(position);
gridLayout.invalidate();
gridLayout.invalidateViews();
try{
Thread.sleep(1000);
}catch (Exception x){
}
//DETERMINE IF THE CARDS MATCH AND IF NOT -- SET CARD INVIS
String message = engine.itemClicked(position, gridLayout);
Toast.makeText(getApplication(), message, Toast.LENGTH_SHORT).show();
//If engine returns a value of WASWINNER, we can end the activity and end the game.
if (message.equals(GameEngine.WASWINNER)) {
startActivity(endActivity);
}
}
});
}
The final result as it stands, is the application changes the image to show, checks for match, if no match changes to not show. And only afterwards, re-draws the interface again with the new values, so to the end user, if there was no match, they never see the "wrong" tile, because it is reverted back to "not show."
Thanks in advance and please correct me if the question could have been asked better.
Okay, I managed to resolve this issue making use of the AsyncTask abstract class. By using AsyncTask, I effectively could "multi thread", separating the comparison logic from the UI logic. As a result, I could manage the UI directly and seperately as shown in the basic explanation below.
By using the onPreExecute() I showed the cards.
BY using doInBackground() I could check and set card show state processing.
By using onPostExecute() I could return the cards to their final view state, directly in the UI thread, based on the results from the DoInBackground() method of the AsyncTask implementation.

Fading a View in a ListView item - with a twist

I'm trying to find some kind of elegant solution for fading in/out a TextView that is part of an item in a ListView.
To give you some context, the listview shows a list of players in a basketball game. The user taps on a name and is provided with a dialog to log an event, for example a shot or a foul for that player. Once the dialog is dismissed the user is brought back to the listview and it is here that I'd like to provide some feedback about the event that has just been logged.
The way I'd like to do it is to have a small string appear for about 5 seconds in the view of the item (player) that has just been tapped on. The small string would display something like "3rd foul" or "4 turnovers".
A naive implementation is straightforward. Change the text of the view to the required string and then start an animation that fades in the view, keeps it there for a while and then fades it out. Problems arise however when a second event for the same player is logged shortly after the first. Ideally the first feedback string should be allowed to stay for the allotted 5 seconds and the second string should fade in/out in the next 5 seconds.
This queueing of animation and text changes on a per-player bases I'm not quite sure how to implement. Furthermore, I'm concerned by the interaction between the animations and the Activity's life cycle. What happens (or should happen) to the queued animations when the activity is sent to the background, stopped or even removed from memory? Or when an item is removed from the ArrayAdapter behind the listview?
Thoughts?
Manu
Don't worry about the lifecycle of the activity. There will be no adverse effects. However if the activity goes into the background during the animation, the animation will take place and you will not see it.
As for haveing one animation wait for the next, simply do this:
// here we will keep track of any listView and when the last animation took place.
// The keys will be your listView identifiers. Here I assumed an integer, but use whatever is a good ID for your listView
private HashMap<Integer, Long> listViewLastAnimations;
// the length of the animation in milliseconds
private static long ANIMATION_LENGTH_MS = 5000;
// put this code where you would start your animation
// get when the last event animation occurred
Long lastAnimation = listViewLastAnimations.get(YOUR_LIST_ITEM_IDENTIFIER);
Date new = new Date();
if (lastAnimation == null ||
new.currentTimeMillis () - lastAnimation > ANIMATION_LENGTH_MS ){
listViewLastAnimations.put(YOUR_LIST_ITEM_IDENTIFIER, new.currentTimeMillis ());
// perform animation as normal
}else{
// set a delay to your animation with
long delay = ANIMATION_LENGTH_MS - (new.currentTimeMillis () - lastAnimation);
listViewLastAnimations.put(YOUR_LIST_ITEM_IDENTIFIER, new.currentTimeMillis () + delay);
setStartOffset(delay) ;
}

Can I resume from the same place where my application left calculating while going on pause?

My application is processing data (which involves lot's of calculation, creation of arrays, clearing of those arrays) is it possible to resume from the place it left the calculation when the application resumes ?
While the calculation is going on I am showing a progress bar which cannot be cancelled using the back button, but in-case the user clicks the home button I do not want my calculation to be lost but instant stay exactly at the point till the application is run again and display the final results.
Thanks
====== Edit ======
I call ProcessingAsync().execute() in the onCreate method
The content of doInBackGround of my ProcesingAsync class is given below: (Using spinner and not horizontal progress bar to show the activity is going on)
#Override
protected String doInBackground(String... aurl) {
recordedDataFile = new File(Environment.getExternalStorageDirectory().getPath(), "Machine_Health_Monitoring/Temporary_Files/Fault" + faultNumber + FORMAT_WAV);
runThisCalculationMethod(2, recordedDataFile);
// showWaitingMessage becomes false after the runThisCalculationMethod() is completed
while(showWaitingMessage){
}
return null;
}
You can create a marker (that shows in which part of the calculations you're at) and a partial-result and save it to a file. When you try resuming you'll first look in the file (if it exists) and continue from the last saved point. After you've finished all your calculations and displayed the results - make sure to delete the file.

"realtime" search using AsyncTask?

I am writing an application that searches a database in "realtime".
i.e. as the user presses letters it updates a search results list.
Since the search can take a while, I need to do the search in background and allow new key presses to re-start a search. So that is a user presses 'a' (and the code starts searching for "a"), then presses 'b' - the code will NOT wait for "a" search to end, then start searching for "ab", but rather STOP the "a" search, and start a new "ab" search.
To do that I decided to do the search in an AsyncTask. Is this a wise decision ?
Now - whenever a keypress is detected, I test to see if I have an AsyncTask running. If I do - I signal it (using a boolean within the AsyncTask) it should stop. Then set a timer to re-test the AsyncTask within 10 mSec, to see if it terminated, and start the new search.
Is this a smart method ? Or is there another approach you would take ?
TIA
First yes, AsyncTask is a good way to do this. The problem I see with your approach is the timer waiting to watch something die. When you invoke the asyncTask hold onto a reference of it. Let it keep state for you so you know if it's out searching or it's has returned. When the user clicks another letter you can tell that asyncTask to cancel. Something like this:
public void onClick() {
if( searchTask != null ) {
searchTask.cancel();
}
searchTask = new SearchTask( MyActivity.this ).execute( textInput.getText() );
}
public class SearchTask extends AsyncTask<String,Integer,List<SearchResult>> {
private boolean canceled = false;
protected onPostExecute( List<SearchResult> results ) {
if( !canceled ) {
activity.handleResults( results );
}
}
public void cancel() {
canceled = true;
}
}
This is safe because onPostExecute() is on the UI thread. And cancel() is only called from the UI thread so there is no thread safety issues, and no need to synchronize. You don't have to watch a thread die. Just let the GC handle cleaning up. Once you drop the reference to the AsyncTask it will just get cleaned up. If your AsyncTask blocks that's ok because it only hangs up the background thread, and when the timeout hits it will resume by calling onPostExecute(). This also keeps your resources to a minimum without using a Timer.
Things to consider about this approach. Sending a new request everytime a new letter is typed can overload your servers because the first few letters are going to produce the largest search results. Either limit the number of results you'll return from the server (say 10-50 results max), or wait until they've entered enough characters to keep results down (say 3). The cons of making the user type more characters is the feedback doesn't kick in until 3 chars. However, the pro is it will dramatically reduce the hits on your server.

How can I fix this touch event / draw loop "deadlock"?

Just want to start out by saying this seems like a great site, hope you guys can help!
I'm trying to use the structure laid out in LunarLander to create a simple game in which the user can drag some bitmaps around on the screen (the actual game is more complex, but that's not important). I ripped out the irrelevant parts of LanderLander, and set up my own bitmap drawing, something like
BoardThread (an inner class of BoardView):
run()
{
while(mRun)
{
canvas = lockSurfaceHolder...
syncronized(mSurfaceHolder)
{
/* drawStuff using member position fields
in BoardView */
}
unlockSurfaceHolder
}
}
My drawStuff simply walks through some arrays and throws bitmaps onto the canvas. All that works fine. Then I wanted to start handling touch events so that when the user presses a bitmap, it is selected, when the user unpresses a bitmap, it is deselected, and if a bitmap is selected during a touch move event, the bitmap is dragged. I did this stuff by listening for touch events in the BoardView's parent, BoardActivity, and passing them down into the BoardView. Something like
In BoardView
handleTouchEvent(MotionEvent e)
{
synchronized(mSurfaceHolder)
{
/* Modify shared member fields in BoardView
so BoardThread can render the bitmaps */
}
}
This ALSO works fine. I can drag my tiles around the screen no problem.
However, every once in a while, when the app first starts up and I trigger my first touch event, the handleTouchEvent stops executing at the synchronized line (as viewed in DDMS). The drawing loop is active during this time (I can tell because a timer changes onscreen), and it usually takes several seconds or more before a bunch of touch events come through the pipeline and everything is fine again.
This doesn't seem like deadlock to me, since the draw loop is constantly going in and out of its syncronized block. Shouldn't this allow the event handling thread to grab a lock on mSurfaceHolder? What's going on here? Anyone have suggestions for improving how I've structured this?
Some other info. This "hang" only ever occurs on first touch event after activity start. This includes on orientation change after restoreState has been called. Also, I can remove EVERYTHING within the syncronized block in the event handler, and it will still get hung up at the syncronized call.
Thanks!
So Rob Green from rbgrn helped me get a little more info on this. I ended up using a concurrent queue to deliver touch events to my game thread, but I still had hanging issues when saveInstanceState got called, so I'm now calling Thread.sleep(16) at the bottom of every iteration of my game thread's while loop. Full discussion here.

Categories

Resources