I have a static textview that has a certain default value set in the XML. Later, I set that variable to something else, but whenever the orientation changes, the value of the static variable returns to the default, even though I'm not reinitializing it. Why might this be? Shouldn't the value persist even after onCreate() is called?
When onCreate() gets called I'm guessing you also call setContentView() as normal. This redraws all of the Views with the default values. You need to handle the configuration changes
See this answer of mine on how to handle it. The recommended way is to use onSavedInstanceState but I normally handle it myself and haven't had any problems...yet
This has to do with the lifecycle of an Android app. Whenever you rotate, your application goes through all the lifecycle method calls. You need to store the current state within a Bundle and restore that data in your onCreate after the rotation has occurred.
During orientation change Android re-creates all layouts. To save the state of the widget you can simply assign an id to the TextView element:
<TextView
android:id="#+id/tv_caption"
...
/>
Related
When I change the screen size in the multiview / split screen mode, the onCreate function in MainActivity is called again.
Because in onCreate I have a ProcessLifecycleOwner observer:
ProcessLifecycleOwner.get().GetLifecycle().AddObserver(this);
I don't want it to be restarted ... How do I know that onCreate has been called before?
I know you can add:
android:configChanges="screenSize"
in the manifest, but unfortunately needs to "refresh the layout" when resizing.
Android is going to manage the life cycle, and the programmer needs to deal with all eventualities. On this page, there's an abbreviated diagram:
That would indicate that you would need to manage the observer in the onStop().
I have an Activity which can open 2 different Fragments by 2 different Buttons. By the default that Activity when it creates, it is opening a Fragment, we call it "The Main Fragment".
The first Fragment to which we are going over by the first Button we meet zero problems with the Rotation, but the second one after the rotation disappears and the screen shows the Main Fragment's content. When I tried to rotate the screen back, I see the Main Fragment's content again. But why it is so, if I didn't write any code, which must return me to the Main Fragment without clicking a button.
What assumptions do you have?
Why this is happening ?
Default Behavior, Actiivty is getting recreated on orientation change so your fragment are.
Explanation
You need to understand Activity Life Cycle to understand why this is happening.
First, “rotating the screen” is not the actual scenario we are talking about today. Because any configuration change will cause Android to restart your Activity. A configuration change might be the device rotating (because now we have a different screen layout to draw upon), or it could be a language switch (because we need to re-write all those strings, which may need more room now OR it could be the scary RTL switch!), or even keyboard availability.
By reloading your app, what the system is actually doing is calling onDestroy() and then immediately calling onCreate(). This way, your Activity is as fresh as possible, with all of the right creation data (even though the user has been with you the entire time).
Now you have following option -
Either Fix Orientation for your app from AndroidManifest.xml
But oviously that is not a very good experience for user.
Save activityState with onSaveInstanceState()
This method will be called before onDestroy(). And, when your Activity is created, there’s a matching step onRestoreInstanceState(), which will also be called automatically. All of these automatic steps mean that you can let the system worry about saving and loading your data, because you planned ahead and mapped out what was important. (Or, you can skip onRestoreInstanceState() and load your saved state from the Bundle that comes with onCreate().
In you integrate Fragment in activity, because activity is getting destroy() so your fragment will also destroy() and will be recreated.
Please take a good read on Handling Configuration Change and this.
Once you understood the concepts things will start falling into your but it will only happen if you will complete your learning curve.
Happy Coding !
That is because onCreate is being called every time the screen is rotated. Probably you are displaying The Main Fragment from your onCreate method. You will face the same issue if you put your fragment display logic in onResume because just after onCreate, onResume is called.
Solution: store the fragment on top in shared preferences that way you know what to display every time onCreate is being called.
I'm converting all my Activities to Fragments so that I can use them in a ViewPager.
I've searched for this but I couldn't find a satisfying answer, so that's why I'm asking it here.
In my Activities, I've written some code in the onCreate() method. I for example call some findViewById()s in order to link some xml-buttons to my Activity. I also make some views invisible in the onCreate(), set an OnClickListener(), fill a TextView with text and remove a Notification, all in the onCreate() method.
My question is: Where should I put this code in the fragment? In the onCreate()? onCreateView()? onActivityCreated()? and why?
Many thanks in advance!
Although Pragnani's answer is close, there's little educational value in it. Besides, there's a more appropriate option to his 2nd statement.
Where should I put this code in the fragment? In the onCreate()?
onCreateView()? onActivityCreated()? and why?
The short answer is: either onCreateView() or onActivityCreated() will do. The view hierarchy won't be created until onCreateView(), so that's the earliest point in the fragment's life cycle that you could inflate the views and attach click listeners etc. Since onActivityCreated() will always be run after onCreateView(), that's a suitable location too. onCreate() may be skipped in favour of the system temporarily detaching the fragment and reattaching it, e.g. when retaining fragments.
Pragnani is correct by pointing out that inflating the views of a fragment is slightly different from inflating views in an activity. More specifically: a fragment does not define a findViewById() method, so you'll need to call it on some other object.
Rather than using getActivity().findViewById(), you'll want getView().findViewById(). The reason for this is that if you use the activity for the view lookups, then you'll get into trouble when multiple fragments with the same view IDs are attached to it. This will be the case if you reuse view ids in the layouts of your various fragments, or if you show two identical fragments that display different data. In both cases, only the first match would ever be returned, whereas you really want to the view to be looked up in the conext of the fragment. That's exactly what getView() returns, the fragment's root view (that you returned in onCreateView()), and thus limits the scope of the lookup appropriately.
1.Left the onCreate empty and just call super.onCreate()
2.Instead of findViewById() use getActivity().findViewById()
always use getActivity() where you need context of the view.
Do all other operations in onCreateview()
I have an app structure like this:
Background: The Parent activity #1 is just holding the tab host, tab widget and is also setting up the 3 tabs to have their content set to the 3 tab activities (tab1, tab2, tab3 activities).
Update: I tried calling my validation method inside
onTabChangedListener in Parent Activity #1 but I got a Null Pointer
Exception. Couldn't really trace it to anywhere. I did
commented/deleted conflicting code but still I am not getting the
bottleneck.StackTrace(PasteBin Link).
Code for Parent Activity #1,Tab#1
Activity
Problem: I want to validate data entered by user in the form field(s) in the individual tab activities onTabChanged event but I am unable to set more than a single setOnTabChangedListener. Am I missing something here? The listener(s) are set in their own tab# activities under oncreate method. Apart from trying the above technique, I had tried setting up the listener in onResume() under the main Parent activity #1. But the on Resume() method was never invoked. I got a null pointer exception too.
Idea behind validation being: I want that while the user is changing tabs, the data should be validated before he can skip over a tab. So, ineffect I would require tab#1 to validate data in a event similar to onTabChanged if tab#2/tab#3 is selected. Also, this would apply if current tab#2 is selected and user selects tab#1/tab#3
Any advice will be appreciated..Thanks for reading..
I want to validate data entered by user in the form field(s) in the
individual tab activities onTabChanged event but I am unable to set
more than a single setOnTabChangedListener.
There is no need for a second OnTabChangeListener and even if you could set it it wouldn't help you. As you constructed the code you need access to the child activities. You can do this by using one of the answers in this question. The problem is, that those answers, except the accepted one, use deprecated methods.
My method, that I proposed in the comments is to have a static boolean field in each of the child activities used as tabs and let all of your activities update that boolean flag whenever there is a change of state of the views in those activities(if you check a CheckBox, enter something in an EditText etc). Then you can simply check the flag for the desired child activity in the OnTabChangeListener. My method should work but your code is a bit messy so you would have to modify it quite a bit.
I had tried setting up the listener in onResume() under the main
Parent activity #1. But the on Resume() method was never invoked. I
got a null pointer exception too.
It's normal that you get a NullPointerException with your code as I haven't seen where you initialize the references to the child activities that you use in the OnTabChangeListener.
Also:
Don't use TabActivity. It's been deprecated in favor of the Fragments framework which is more flexible. Those fragments could help you because, I think you want to stop changing the tabs if the validation of the current page fails and the OnTabChangeListener might come a bit late for that(but I may be mistaken about what you want).
As a side note, use equals in your code to test String equality and not ==.
I change Linear Layout background image via this code:
mainlayout.setBackgroundResource(R.drawable.back);
But i want do this on every time that activity starts, In first start and switching between activities. I put this code inside an IF statement in onCreate() but background not change! Of course when i set this code to a button works fine! How and where i have to put my code?
my complete code is:
//check theme id
if(myDbHelper.gettheme()==1)
{
mainlayout.setBackgroundResource(R.drawable.back);
}else if(myDbHelper.gettheme()==2)
{
mainlayout.setBackgroundResource(R.drawable.blueback);
}
You need to put your code into the onResume() method.
Here are details that will explain why
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
You may want to refer to the Android activity lifecycle, but I'd recommend the onResume() method.
I'm assuming based off your code snippet you have the image you want as a background as a drawable resource already in project. If so you could just go into the XML and add into the linerayout:
android:background="#drawable/back"
This should just set the background within the XML layout avoiding having to have code set it within one of the activity life-cycle functions.
Though in the case you wanted different themes as I just saw in the original post (seemed to be edited since I was typing this up), you could try storing the constant int of the R.drawable that the user wants as the background or theme, and have your DB Helper's getTheme() return that reference to set the background without the if statements.
Such saying the user changes their preference to R.drawable.black or .blueback store the int within the DB so it get return by gettheme rather than a 1 or 2 enumeration. Not sure if this would be a best practice though.
EDIT: Are you sure theme is either 1 or 2?
If you want to do it everytime, why don't you just define it as mainLayout's background in your layout.xml? Otherwise, use onResume() rather than onCreate().