I don't think my future lies in Android development, as I am consistently failing at the simplest things...
I've got a button with the label "Game Slot 1". When the user clicks it, I succesfully take them through a couple of activities in which they create a new character. I save the game name in an SQLite database, and the next time I launch my app, I can quite happily dynamically change "Game Slot 1" to the name of that slot's game from the database. Perfect.
But how on earth do I get it to update the view in the same manner when I return to that activity via the back button, or having called finish() on all the subsequent activities?
I'm sure it's something to do with onResume(), and maybe invalidate(), but I just can't seem to find an example.
Is invalidate overkill just to refresh a few UI elements onResume()?
How the heck do you use it, anyway, even if it is?
Is there a better way?
Many thanks in advance for any help offered...just try not to laugh at how simple this probably is! :)
Cheers,
James
That sounds like something you could do in onResume, just query the database and call setText on the element of interest. You should not need to explicitly call invalidate.
Related
My app represents funny sentences that my users upload, and in order to know which sentences are better I want to know if the user has taken a screenshot. The only related thing I found is from Google Maps. Anyone know how to make a "screenshot listener" or which method it invokes? Thanks.
One way to do this is by creating a class which is implementing FileObserver. Then add listener when you are loading activity ( by using onStart() activity's method) and remove listener when you are going out of your activity (by using onStop() activity's method).
Once you get FileObserver event, you have to be sure that is a picture creation.
Note that this method is not 100% safe but it's simple to make it works !
A strange behavior I'm tearing my eyes on since early this afternoon, I'm givin up understanding but perhaps someone has an idea (yeah, I'm a beginner, some PROBABLY has an idea ^^).
Situation :
MainActivity.java (first one to be called, only one of interest here)
public ExpandableListView listClubs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listClubs = (ExpandableListView) findViewById(R.id.expLstMainClubs);
AppGlobal.CreateDistricts() ;
ELVAdapterDistrictsClubs adapter = new ELVAdapterDistrictsClubs(this);
listClubs.setAdapter(adapter);
}
it's the only code in the class. Basically, I'm filling an ExpandableList with an adapter that relies on what's created in the CreateDistricts() method (creates business objects, Districts containing Clubs containing Members, Events, etc.).
Basically (again ^^), everything runs fine, on first start the ExpList works as expected, as well as the rest of the app. If I hit the back button from the MainActivity, however, and rerun the app, a "strange" (to me at least) behavior occurs :
The ExpList is loaded twice in a row - first one with the data, works fine, and just below a duplicate (with the same 2 Groups, i.e. here the only two Districts in my sample data), which doesn't work at all (if you try to expand it, it crashes the app).
Frankly, I'm lost - I've tried some things on the various on[Pause/Stop/Destroy/Start/Resume] etc. to no avail (therefore, there is yet nothing done on this side, no override, as it seems not to bring anything good).
As the onCreate will after the onDestroy load the bundle, it should load the ExpList as it were, and in this case there might be a conflict between the "old" groups/children and the actual ones (currently, data is simulated, but will afterward come from a remote data source), and I haven't decided yet what the best "save" behavior is, i.e. if I should find a way to obliterate the ExpList onDestroy in order to be sure it's 100% recreated anew (and how does one do that ?) and start from scratch, or if I could use the ExpList as is, while updating it's content, in order not to lose the previous selection. It may be irrelevant to complicate matters in order to do that, the first list being not so big and quite quickly used to reach the second activity...
Anyway, I suspect it comes from around that part, the bundle load after destroy and rerunning, does it reload the ExpList as is and then I add things instead of first deleting ? What I found confusing is that the next activity (reached simply by clicking one of the items of the ExpList) displays a similar ExpList (filled with Months and Events per Month for the selected Club), and doesn't present the same strange behavior after a destroy... and both have an almost identical ExpList declaration in their original xml layout so... well, perhaps tomorrow morning I'll see the light, but if anyone has an idea, feel free :D
The more I write, the more I think I should first clear the ExpList but... I don't see how exactly. I've tried
listClubs.removeViewsInLayout(0, listClubs.getCount()) ;
but it just doesn't seem to do anything.
Thanks in advance
Nothing related to Android behavior - I was recreating everytime the whole set of BO behind if the base ArrayList of Districts was not null... instead of simply getting out of the method, but it raises another question - how was the state of this ArrayList, which is declared in a subclass of Application serving as Application in my manifest ? I'll have to make some tests about that...
So after a while of programming android apps(1 uploaded on market, have 3k+ active installs with a 4,7 rating), I started to wonder, how can I make my app even more awesome. I realized, that I couldnt really add any really new, and world changing features, so I started to inspect the performance, and how to optimize just about everything, how to find the best cpu/memory usage ratio, and so on.
Anyway, I found out that onCreate will run in the case of rotating the screen, which is quite logic, but there are some(big) calculations, that I surely dont need to redo after every rotate. One of this is iterating through a csv with 6500 rows, having 4 columns, 2 of it always contains some data, 2 of it not always. The 2 column with datas will be used for autocomplete adapter, the another 2 is optional for a feature, but it still need to be initialized. Currently, this is running in an asynctask, triggered at the end of the onCreate, and takes about 3 seconds on my HTC Desire S, which has a quite good CPU, so lower budget devices will have a longer initialize time after every rotate which is surely not I want... It wont crash the UI, but there won't be any autocomplete until thoose seconds are over.
SO: my question is, can I do this in some separate method, for example a constructor(like in standard java), or is it a bad practise, because the special lifecycle of activities? I mean, I instantiate my activity the way the "constructor" will run, and just after that, my onCreate will run. In case of rotating, my "constructor" won't run again, but the onCreate will. Stability will still be my nr1 goal. Or, is there any good way to do this? Something that is created for exactly like this, which im unaware of? I really want to improve a lot in this matter, and I would really appreciate some help in this, preferrably from ones with experience in this, but any help is welcome! :)
For example, if I want to make a new activity this way, I would do it something like this:
new MyActivity(some parameters);
so the constructor runs, which ends something like this:
startActivity(new Intent(context, MyActivity.class));
So this way, the constructor runs, my variables will be initalized(not connecting to any view etc), and after that, my activity can run its onCreate variable anytime it has to.
Pardon me if Im wrong the syntax, I just fasttyped it :)
You should decouple this logic from your activity. There are many ways to do this, but the end goal is to have your csv parsing done in a different class, and this class should expose information about whether or not the data has already been parsed. So, in onCreate, you call your class to get the data. If it already exists, you get your cached data immediately. If this is the first time the method is called or for some reason your cache has been cleaned up, you parse your csv file and do whatever calculations you need.
you could take a look at onRetainNonConfigurationInstance which can return an object which you can access after your activity has been recreated.. so you would simply return an object containing all your processed results of onCreate and the next time around you check if there is a getLastNonConfigurationInstance() - and don't recalculate everything
I am trying to figure out how, when a user lands on my activity screen, it is "reloaded" as if it were being loaded for the first time.
I don't want my user hitting the back arrow and coming back to my activity with old information.
As it is now, when a user "comes back" to my page, the database list isn't being repopulated, and information they typed into EditText fields remains there.
I want the page, everytime the user comes to it, to be like it's their first time there.
Have you ever tried using recreate() in your current activity? Try using it after your new values are populated.
Or you can just put everything that's in the onCreate() on the onResume. A bit ugly but it works.
I have to disagree with Kartik on this, as I understand, android:noHistory='true' will remove activity from application stack. So when user hits back, user will not be able to see the activity at all.
About activity not retaining its value, I would not recommend you this, as user expects that all values would be retained when back is hit, unless there is some specific requirement that you are trying to meet.
So I guess solution to your problem is, as others have suggested do your initialization on views in onResume(). But just doing this may not be sufficient, as views like EditText will by default cache the values anyways. So you might have to manually clear those in your on onResume(). Will keep looking to find any 'perfect' solution if any to this problem.
I had solving similar problem like yours and I solve it whit lunch mode.
I think the best is to take a look of this set the lunch mode in single instance and then
in you onCreate and onResume you can code to refresh you view just the way you want it.
copy requred code into onResume() from onCreate() method
Hoping someone can assist with this what seems to me a peculiar problem.. My mind is pulsing a little here as it's blown my understanding of the Android Activity Lifecycle.. Let me try to make things clearer.
Problem: I'm receiving a 'StaleDataException' during the 'getView' method of a custom adapter (extending BaseAdapter) that I use on an activity to populate a GridView. Sounds straight forward so far.. When I first go into the activity, the adapter is working as expected and the grid is populated.
I have a button on the activity which fires off an Intent to allow the user to take a photo, and comes back via 'onActivityResult' saving the image to a database. This all worked also. In fact I wrote that portion first, then added the adapter & gridview afterwards.
Now the StaleDataException is occuring when I've gone to the camera to take a pic, and then click OK to return... I have lots of Log statements in most events on my activity, and very bizarrely the StaleDataException is occuring before ANY of these events are triggered... before OnActivityResult/OnResume etc.
SO I'm quite confused as to why the Adapter is being accessed before I've properly returned to my activity and before onActivityResult/OnResume have been called..
Debugging the steps that lead up to the exception, it all occurs on this line :
String contentType = dataCursor.getString(dataCursor.getColumnIndexOrThrow(DbStatics.ACCIDENTS_MEDIA_KEY_TYPE));
What's also baffling me is the dataCursor is actually Open and the first call (getColumnIndexOrThrow) is also returning a value.. so its the getString() which leads to the exception.
So I hope that's clear enough... and really really hope someone might be able to shed some light on what's going on..
Many Thanks,
I recently encountered exactly the same problem in almost exactly the same scenario.
(I'm using a Gallery rather than a GridView)
In my case, my code worked fine for months - until I recently updated my N1 to 2.3.
My solution (after much brain pulsing of my own) was to not call startManagingCursor on the cursor I pass in to my adapter.
Instead, I manage the cursor myself.
That seemed to clear the problem up for me....though I couldn't tell you why...maybe someone more experienced can shed some light.
Hope this helps you.