I have a problem when starting my app and another one in split screen mode, when my app's window is enlarged over 2/3 size, my main activity restarts, how to prevent it? When I change the size by less than 1/3 nothing happens .... it doesn't restart. Sorry i didn't provide the code.
Activity restarts are common in Android. They happen whenever there's a configuration change. That includes resizes. You can override that behavior in the manifest (at the cost of being unable to switch layouts at different sizes), but you're better off just being able to support them.
To turn them off in the manifest, use android:configChanges="screenSize" on the appropriate activities. This will cause Activity.onConfigurationChanged to be called instead when the screen is reized.
Related
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.
It's well known that on screen rotation activity will be recreated and we need to survive configuration changes if we follow the MVP or MVVM patterns to keep alive Presenter or ViewModel(Example: to avoid double calls to WebAPIs). The question is, do I need to keep alive my ViewModel or Presenter if by business requirement we don't have screen rotations(only portrait mode)? Thanks a lot in advance.
Short answer: Yes, you do.
Long answer:
Orientation change is one of possible configuration change events, there are others (like Locale change, hardware Keyboard open/hide, screen size change (due to enable/disable Split Mode) etc.).
Moreover, configuration change is one of possible causes of activity's recreation - it can be re-created w/o configuration change by the system when the activity is in background and system goes low on memory. You can simulate this with "Don't keep activities" developer option enabled.
I have a workflow with several screens with different questions and answer-options. So there is a question on screen 1 and the user makes his choise -> the user hits the continue button -> screen 2 opens with another question -> user makes his choice and continues -> screen 3 opens etc...
But actually I'm not sure which is the best way to implement this behavior in consideration of a good maintainability and clearness. I think they are at least three options:
Every screen gets its own activity and layout file and I pass the choosen data trough intents.
1 Activity and different fragments, each fragment has its own layout. If the continue button is pressed, the fragment will be replaced with the next fragment.
1 Activity and different layout files. Just the layout gets replaced and everything else is handled in the activity.
Actually I already started implementing with option 2.) but I don't know if this is not "too much".
The Android API guidelines say that you should use Fragments for multipane UI and for reusability. But actually I don't want to build a multipane UI in this case and the fragments are not reused. So maybe 3.) is the way to go? Or even 1.)?
I would choose your option # 3. The reasons are:
Activity takes some memory compared to fragment or layouts. The interface between activities and fragments is a bit awkward, though I got used to it. I don't recommend it for your case.
I like fragments. However if all the fragments are similar in looks/feel, then why take the computer time for hiding/showing or replacing them. The reason for fragments is stated in Google web page like at Building a Flexible UI. I don't think you need a flexible UI as said in Google's intention.
I would suggest one Activity, at least one Fragment for all the questions/answers. You simply use one layout to change text/content. If the UI is different, then replace the layout with another. It's quite normal for an Android app to have so many different layouts anyway.
Android takes some memory to load layouts but it's quite fast and efficient.
For option 3 design:
You can use the inflate() method to load a certain layout and to replace one. A good example at SO link # Android layout replacing a view with another view on run time
There's three screens. The first is the main screen, the second is a filler screen and the third contains a screen with 4 buttons.
Main screen contains one button that leads to the 2nd screen, 2nd screen contains another button that leads to the 3rd screen.
Images are stored in drawable-hdpi.
The outofmemoryerror occurs when I press the button in the 2nd screen, specifically the android.app.Activity.setContentView in the onCreate on the 3rd screen.
The app works fine if it's only going from the 1st to the 3rd screen but we need to add some screens in between the 1st and 3rd screen.
Here's the logcat:
Edit: I have a S4 (International) but it works fine on a Nexus 5.
It looks like you are loading a bitmap into memory. In an android app you only have about 16 megabytes of ram available, so you can run out of ram very quickly, and an outOfMemoryError will occur.
You can fix this by using the resource id of the image instead of a Bitmap object. For example, use:
setContentView(R.layout.view_id);
where view_id is the id of the view you want displayed.
The use of images inside your activities can lead to occasional OutOfMemoryError, if you don't follow some guidelines.
First of all, take extreme attention when declaring, initializing and using Bitmaps inside you code. These objects are managed by the system in a special way, this is a good place to start if you want to use them efficiently.
Anyway, since you didn't post any code that show the use of Bitmaps, I focused the attention to a single line of your question:
Images are stored in drawable-hdpi.
Are the images stored ONLY in such directory? Well, this is a bad practice and it's a source of memory errors ;)
When you ask Android to initialize a particular Activity, all the images declared inside its XML are loaded from a particular drawable-**** folder, depending on the screen size of the current device.
For example, a mdpi device will start to look inside the drawable-mdpi for the image named img. If it's not found, then it looks with a cascade behaviour inside all of the other drawable folders.
The problem is here: if the img is found in a different folder than drawable-mdpi, first it's scaled by the system to match the scaling factor for mdpi. Hence, another copy of the Bitmap is created.
Since all your images are inside a single, high resolution folder, the scaling operation will be executed by every non-hdpi device that will run your application. This is not good at all (here some docs).
The solution is to create different scaled versions of the same image and store them in multiple folders, like: drawable-ldpi, drawable-mdpi, drawable-hdpi, drawable-xhdpi
There is a convenient tool that does the dirty job: 9 Patch Resizer
Hi and thanks in advance for your time and attention.
I actually have 2 questions i'm not too sure about building an android app. Pretty basic stuff I believe:
1) My app is fully on Horizontal mode, like AngryBirds for example. When it starts the user figures out he should hold the phone like that, if he isn't already. And that is setup in the manifest for all the activities and works fine. but is there a way to prevent the physical device tilting to call onCreate again? can i override it's method or whatever? the reason i'm asking, is because i have a few ButtonViews that after you click on them, change their picture. i am using onRetainNonConfigurationInstance() to save the array of those ImageButtons, and i even mark the ones changed with the ImageButton setTag() and getTag() methods, so when onCreate is called because of the device tilt it gets the saved array from getLastNonConfigurationInstance() , but i've been trying to make it work for quite some time now and I just can't get it right. After the device tilt (I'm actually using the emulator so it's Ctrl+F11 but i believe it will happen with a device as well) all of the ImageButtons loose their pictures.. Long story short - are there better ways of doing this that you can recommend or is preventing the tilt from doing anything is possible or better?
2) What is the best way to know how many seconds the user has been on a screen? I tried to use two longs that i get via SystemClock.currentThreadTimeMillis() as follows: get the starting time onCreate, and the ending time on the method i call to move to the second intent just before i startActivity. but I think because they are called from different threads, the endingpoint - startingpoint is not correct. What is the way to insure both of the methods of SystemClock.currentThreadTimeMillis() are called from the same thread, the main thread of the activity that i'm stopwatching? Is there a better way to go around this?
Thanks again.
You are doing the right to handle orientation change. Please refer to this link http://developer.android.com/guide/topics/resources/runtime-changes.html . This will help you to get it working.
Good way would be to count the time between onResume and onPause. OnCreate is not called all the time if you are resuming activity.
1) You can try adding the property android:configChanges="orientation" to your activity in the manifest file. It worked for me when my dynamic Action Bar tabs got messed up upon rotation of the screen.
You need specify orientation in android manifest for each of your activities, it will not call onCreate then. android:screenOrientation look at http://developer.android.com/guide/topics/manifest/activity-element.html
User see and interact with your activity starting since onResume and ends on onPause. Other time it does not guarantee that user actually see and can click on something in the activity. System.getCurrentMillis() is good enough.