I just want to ask why my app crashes with the following conditions.
I am working with fragments with only one activity. In my fragment, say FragmentA, I create views dynamically (inflating them). They work fine. But when I press home button, and go to the app again, I expect that FragmentA will be displayed but unfortunately, it throws NullPointer.
There is no errors in my android phone[GingerBread] but on my Tab, this error happens. Any help will be higly appreciated. Thanks.
You are not providing enough information to reliably answer this question, but the difference your're seeing is probably related to different behaviour of the garbage collector on the two different devices. As they are running on two different devices they will also behave differently.
The null-pointer you are seeing I would guess stems from wrongful use of member variables in your fragment.
When you go to the home screen and back your fragment will (or more accurately CAN) be recreated. Read: destroyed and re-instantiated using the argument-less constructor.
So make sure your fragment(s) are properly saving any needed state in onSaveInstanceState and restore this information in OnCreate/OnCreateView or whatever you're using.
Related
Hi Xamarin/MvvmCross devs,
I am having a problem with the MvxCachingFragmentCompatActivity, or I think it's a problem. I don't know if it's expected behaviour or not.
In my app I use fragments inside a container view. I'm having a problem with the FragmentBackStack when the activity is being restored after destruction. If I go three levels in from my initial fragment, go into the background and come back to the foreground only the last two views are restored. Note this is with "Don't keep activities" switched on in developer options.
Is there any specific setup/indication I have to give to MvvmCross to indicate too them that I want them to handle my viewmodel save/restore functionality. I don't see any in the samples I went through.
I use to use a manual approach with older versions of MvvmCross where I stored a reference to all my viewmodels in the ContainerViewModel and then just read that up when it's restored. But this doesn't work particularly well when you can have multiple of the same view on the backstack.
I have nothing special in the app, it's base usage of MvxFragment for all the views. I do have a custom presenter, but I only override ShowFragment so I can show popup views instead of replacing. None of the views not being restored uses this functionality, so it's not interfering with anything.
Any help would be grately appreciated.
Dane
Update 1
Keep in mind that views in this case are MvxFragments.
while researching this I found some weird backstack behaviour associated with the MvxCachingFragmentActivity. While doing the restore functionality I got fragment tag not found in cache errors, so I added this
FragmentCacheConfiguration.RegisterFragmentToCache<View, ViewModel>(typeof(ViewModel).FullName);
When I add this for my view that's displayed second (after the first view), the first view is never added too the backstack. Causing a weird back navigation bug where back would close on the second view even if AddToBackstack is set too true for the first view we navigated from.
When I remove that line the navigation works completely fine. I have no idea why that is.
There were two reasons the MvxCachingFragment was not restoring the fragment backstack properly and had the weird navigation issues after coming back from the backgroun.
I did not set RetainInstance = true; for the fragments. Since I had many I created a base fragment using MvxFragment and set Retain Instance true in the constructor.
I did not have MvvmCross-Json-Plugin installed. Which is used for deserializing the stored viewmodel information from the Bundle.
So, I'm still new on Android Fragments, but if I got it correctly, when you remove a Fragment and stack it to the back stack with addBackStack (according to Android Developer's Fragment lifecycle) you get this portion of view destroyed and when it pops up to the screen again it has to reload all it's components.
I'm specially concerned with that because one of my fragments contains a map, which is a lot of data to reload (specially if using 3G).
In that case, is it a better practice to implement hide and show to all my fragments when manipulating them?
I just see a little problem there because I'd have to create my own stack to know the order they were called and have to be shown again.
Well, it's now a huge problem, but I wanted to hear from someone if it is worth putting effort on it to implement this approach instead of the existing back stack.
Thanks in advance!
Using the ´attach´ and ´detach´ operations are another way around to your problem. The fragment instances will still exist, but deactivated and not visible, and you can recover them using the FragmentManager
If one of your fragments contain google map, it's better to use show/hide operations with the fragment views in order to avoid google map black flickering bug. Check my answer: https://stackoverflow.com/a/25206078/2999943
I was using ActionBarSherlock and ViewPager to have 4 fragments as the tab pages in a SherlockFragmentActivity.
In normal conditions, this solution worked fine.
However, if the application exited abnormally, i.e., killed by the Android OS because of memory shortage, the ViewPager was unable to attach the newly created fragments to the activity any more when navigating back to the SherlockFragmentActivity.
With lots of debugging, I finally found out that SherlockFragmentActivity 'remembered' the fragments attached to it. When it was re-created, it would re-create and attach the fragments to itself, that prevented ViewPager from attaching any new fragment to the activity.
I worked around this issue by overwrite SherlockFragmentActivity#onSaveInstanceState with an empty implementation to force SherlockFragmentActivity to forget all the fragments. But I still have not any perfect solution.
I suspected this is a defect of SherlockFragmentActivity.
As a summary, I think SherlockFragmentActivity has a defect of restoring inner fragments when working with ViewPager.
Did anybody encounter the same issue?
Based on what you have said, I see little evidence of a bug here. Your solution is a good one which is widely used.
However I do want to question your analysis. If the fragments are static (XML) then Android will recreate them automatically. However, if you are creating the fragments dynamically ( and I assume you are if you are using tabs) then the Android system will not recreate them automatically after the activity is destroyed. In this case you should use onSaveInstanceState to programmatically restore the fragment/tab.
Although you have not mentioned the issue of configuration changes , if you are using ABS, you should not attempt to handle the configuration change in your app. This is the only deviation from "standard" that I have encountered whilst using ABS.
If you are looking for high quality responses here then I suggest that you post code and a logcat trace.
I've encountered similar issue. Solution works for me:
At first, fragments are being re-created using default constructor. So if You passing some args in your custom constructor to fragments, You should save 'em duriong onSaveInstanceState and getting 'em out in onCreateView().
It will save your fragments if whole app is not killed by OS.
To restore fragments after whole app re-create, use SharedPrefs to save important data.
Good place to do it in onStop() method and restore in onCreateView().
If You need code sample let me know, but it seems it would not be a problem for You.
I have a special flow of fragments in my app, so I need to be able to switch to any fragment, while keeping fragments in memory whenever possible (so if it's tight on memory, it's ok that the fragment will be released).
So far, I've succeeded doing a replace of the current fragment, but the thing is that the previous fragment is always being destroyed, so if I go back to it (using the action bar, for example), it's re-created and that takes some time.
The reason I use fragments instead of activities is the nice usage of the action bar, the ability to put multiple fragments inside the same container, the non-flexible activities-intents usage, etc...
The reason why I don't use the "Back" stack is that I wish to go to any fragment from any fragment, since the flow can change.
Here's a snippet of my code:
Fragment fragment=... ; //get the fragment from cache or create if not available yet...
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.mainActivity_fragmentContainer, fragment).commit();
I have also tried to use ViewPager, but since I don't want to have the sliding effect (which allows you to slide to other fragments) and since one of the fragments already include a viewPager, it's an obstacle. Disabling the sliding effect on the main viewPager somehow disables it on the other one.
BTW, I'm using the android support library for the fragments and not the native API.
my question is:
how can i achieve full control of which fragment to go to , while maximizing speed and avoiding too much memory being used for fragments ?
EDIT:
for now , i use the next workaround :
for the onDestroyView , i take the parent of the created view and remove the created view from there .
for the onCreateView , if i already have the created view from before , i return it .
however , i think it's a very risky thing to do , since i'm not sure of how fragments managing work , so it might cause weird problems . plus ,i'm not sure what will happen if android decides that it has low memory - will it destroy unused fragments (which is good) or will it cause out-of-memory exceptions (which is bad) .
I agree with your comment regarding "it's very risky". Since the consequences of your approach are not really clear, I would not recommend using this.
To better understand your issue and to give you some indications:
what do you consider to be slow? I keep switching fragments "like crazy" too, and it works OK on a tablet, however on some low-end phones it takes much longer - but is still acceptable
How much work do your fragments need to be created? ie what kind of underlying data needs to be preapared each time? (again, I have several list fragments with more than 1k entries, they get prepared each time, and it's quite fast)
how do you exaclty replace fragments? In particular do you call getFragmentManager().executePendingTransactions();
One way to accomplish your goal is to use FragmentTransaction.show and FragmentTransaction.hide. You can use Fragment.isAdded to determine whether to show or to call FragmentTranscation.add the first time. The downside is that you won't get Pause/Resume events when fragments are shown and hidden; you will need to override onHiddenChanged. You will also have to manage your own stack if you want to support back navigation.
I'm looking for the the best way to reproduce, in an Android app, the behavior of the iPhone UiNavigationController within an UITabBarController.
I'm working on this Android app where I have a TabActivity and 4 tabs. I've already gone through a lot of posts regarding the use of activities and tabs and how it's not a good idea to use activities for everything, which seems fair enough. I decided to use one Activity on each tab anyway, since it makes sense in my application.
However, in one of those activities I have a deep navigation tree with more than one branch and up to 12 different views the user can go through.
The problem is: Android controls the navigation through activities inside an app, if you click the back button it will go to the previous one, but if I'm navigating through views, using one Activity, and I click back, it just finishes it. So how can I have a smooth navigation behavior between views in an Activity?
I had implemented this using a TabActivity with FragmentActivity as each tab. Utilizing Fragments API you can organize the code just like you would be using 12 different activities, still using only 1 for each tab in fact. Fragment's framework will handle back key press for you to show previous fragment instead of closing the entire activity.
There are some problems with such approach, for example, there's no MapFragment, but the workarounds can be found here on SOF.
You will need Android Support Package if your minimum SDK version is lower than 3.0.
Well I know very little about UiNavigationViewController, but I guess you want something to navigate between different Views. As you are using TabActivity, every tab should load into a separate Activity.
But since you want to branch it out, using that many Activities is not a perfect solution, neither the ActivityGroup too. The better solution, as per my opinion(I have run into similar problem once) is to have the main or root tabs loads into separate Activity, but for their branches, use the ViewFlipper, which flips the Views. So the whole Layout(Subclass of View) can be flipped.
You may run into some problem while flipping more than two Views (as what people say, though I never had any problem). So in that case you can use layout.setVisibility(View.GONE) to hide the layout and just change it with View.VISIBLE for next view.
And about the concerns of back button, you need to store the last used View or Activity into a variable, and in the override of onBackPressed(), just need to call them.
There might be better solution than this, not that I can remember, but yeah it's the easiest solution I can come up with.