startActivity doesn't work from a Fragment in HoneyComb - android

The onCreate() method is called but the new Activity never appears. No errors are logged.
Follow up - There was no problem with calling startActivty() from a Fragment (we had a bug in the second Activity that caused it to exit immediately).
startActivity() from a Fragment works exactly like startActivty() from outside a Fragment.

A fragment should not be calling startActivity(), IMHO. A fragment should be telling its activity to display something, and the activity should be deciding how to do that. In some devices, that might be launching another activity. In some devices, that might be by adding a fragment. That decision should be made at the activity level, as it is the activities that are deciding what fragments go in what activities, based upon screen size.
Here is a sample application where a click on an item in a ListFragment causes either a separate DetailsFragment to be updated (for large/xlarge screens) or pops a new activity (for normal screens).

The problem was a bug in the second Activity that caused it to exit immediately. So to answer my own question, there is no problem with calling startActivity from a Fragment. It works exactly like calling startActivity from outside Fragment.

Related

Replace a fragment from other activity than the host

I have a MainActivity with a container FrameLayout in which I change multiple Fragments (Fragment A, Fragment B etc).
In one of this fragments let's say Fragment A I have to open another activity (Activity X).
The problem is that from this activity when I press a button I have to change Fragment A with Fragment B (in the background somehow) and after that, slideout Activity X (with translate animation), and slidein Fragment B ,all this without restarting the MainActivity because I have to keep the state.
How can I do this?
Thanks
Android uses loosely coupled components as its main building blocks. As you know, Activities are one of the main Android building blocks. Thus, interacting between activities are very restricted to a few ways.
Passing data via Intents by startActivity(), startActivityForResult() etc. This way is useful whenever you are starting new activities.
Sending broadcast Intents. This could be useful once you want to send a signal to your another app's component.
Utilizing shared Application object.
Java static fields and some other ways.
In your case I would recommend you to use a Dialog Fragment instead of your second activity, if your second activity is just a login activity or something like that.
UPDATE #1:
If you really would like to keep your second activity, so I would personally recommend using local broadcast mechanism.
Also there are another way to get this done. You could start your second activity as startActivityForResult and then whenever user gets back from your second activity to your first one, your first activity can get informed by its onActivityResult method. There you could switch those fragments.

Force onDestroyView on a fragment's view

I'm writing an app that loads user profiles and user's ratings for different places. The app uses fragments pervasively, and it's relatively easy to jump from a profile to a rated place.
As a user clicks a profile and gets to a rated place, they can click another profile on a rated place and go on and on.
The problem I'm having is memory related, when I'm looking at a ranked place and I click a profile, I switch from one Activity to the next. In both of these activities, after setContentView I load a fragment dynamically into layout space.
Now, as I shuttle between these activities, onSaveInstance state is almost always called, however since the Fragment displaying whatever was in the foreground before the activity switch, onDestroyView is not called.
What I would like is when onSaveInstanceState is called in these dynamic fragments, it to force onDestroyView to be called as well.
The only time onDestroyView seems to be called is when I add a Fragment to the back stack. When another activity comes to the foreground and this fragment is stopped, I'd like on DestroyView to be called as well.
The current workaround I want to implement is have an empty fragment with no view, and every time I call startActivity(Intent i), load this dummy fragment to destroy views and start the next activity. Then, when I come back, pop it off the back stack and restore the actual last fragment.
This however seems excessive. So, for a stopped fragment in a stopped activity with a new activity in front of it, how do I force it to destroy it's View?
First, you should not force or satisfy onDestroyView to fix your code, that's the job of the FragmentManager and the Android lifecyle # Pausing and Resuming an Activity. If you want to work with your existing code, use the other override methods onPause() or onStop().
Without posted code, I assume you're using the replace() method to display one fragment over another. This more or less forces you to manage the fragments yourself, some developers actually succeed in doing so with some struggle (look at other SO questions).
So my suggestion for you is either:
Maintain your own states, and show the proper fragments based on the state.
Use the BackStack and let the Fragment management handle the stack/states.

How to close the activity from current fragment and go back to previous activity in android?

I am having multiple activity in my android app as well as multiple fragment for each activity. From a fragment of third activity, I want to close the third activity on a back press. I have tried using this inside onDetach() function.
getActivity().finish();
This closes the current activity but while opening the same activity again, the app crashes.
finish() is the final call before the activity gets garbage collected.
You should either not call this at all since there's no real reason to do so. If you do want to return to it later, you can't. You can only create a new Activity. As for fragments, anything that happens on the parent happens on the fragment too.
If you want to close a specific activity, you have to keep a reference to it somewhere where the fragment can access it. Preferably wrapped in a WeakReference so it won't leak memory.

Retain Fragment state between Activities

Its possible to retain a Fragment between Activities?
Lets say I have Activity A with Fragment F_Left placed at the left and Fragment F_Right placed at the right. If I want to launch a new Activity and keep Fragment F_Left... how can I do it?
Can I retain Fragment F_Left state between activities?
Note that I want to launch a new Activity because Fragment F_Left is my app menu and Fragment F_Right changes completely the context of the user operations... and my app have many of operations, so it makes sense to have an Activity per operation.
I know its possible to retain Fragment within an Activity, but as Fragment life cycle is closely tied to the container Activity I don't know if this is possible keep Fragment state between Activities.
Since API Level 13 (HONEYCOMB_MR2, June 2011), you can save and restore the state of a fragment across activities.
To save the state, use FragmentManager.saveFragmentInstanceState(), providing a reference to the Fragment whose state you wish to save. The Fragment must be attached at the time you attempt to save its state.
To restore the state, use Fragment.setInitialSavedState() with the return value when you instenciate the same Fragment.
myFragment = new MyFragment();
myFragment.setInitialSavedState(appState.getMyFragmentState());
fragmentManager.beginTransaction().add(R.id.container, myFragment).commit();
You can persist the SavedState object across activities as you would any other object; one way is to subclass Application as shown above (appState is the instance of our subclass).
Based on your response to my comment, I have a slightly different answer. It may not end up being the best answer in your specific situation, I'll let you decide that. :)
Right now you are bundling your fragments in activities because that is what made sense to you, but really, you can probably treat the entire process as one activity and use fragment transactions to hide & show (or create and destroy) fragments as needed.
Since you won't be creating and destroying activities, your menu fragment on the left will be left untouched, and you won't have any problems with its UI state. The set of operations you want to run (which no doubt includes all sorts of different fragments on the right) does not need to be launched in a new activity - but you will have to find a way to manage the logic you need for the fragment transactions (either in your one über-activity or in some kind of OperationsManager class).
I think this will end up being a lot smoother for the users of your application since the single activity just remains running - and you are only changing the parts that actually need to change.
If I want to launch a new Activity and keep Fragment F_Left... how can I do it?
Don't launch a new activity.
Can I retain Fragment F_Left state between activities?
Not automatically. It is not the same fragment. You would pass data between the activities for use by the fragment no differently than you would without any fragments at all.
To potentially answer your original question, if you fire off another activity then I believe that you can save your fragment from your first activity by calling FragmentManager::putFragment(...) when onSaveInstanceState(...) is called and then getting it back later, e.g. in onCreate(...).
However, I have to agree with Mark D's response.
Incidentally I'm doing something similar in that I have a dual pane setup whereby the left pane if fixed with a number of options with each option invoking a different fragment in the right pane. Furthermore selecting an entry in the right pane can result in the right fragment being replaced by another one.
However, I have taken the approach whereby by left fragment is only responsible for displaying and handling responses from the immediate fragment which appears in the right hand pane. Furthermore each right-hand fragment is then responsible for 'replacing' itself with a new fragment and handling results sent back to it. I'm using setTargetFragment, getTargetFragment, and calling onto the target fragment's onActivityResult method to pass results back.
For me the approach I've taken is no different from when my app runs on a phone with a single pane whereby the initial option's activity only knows about the activies it fires off and subsequently these new ones fire off further activies which they know about.
It should be mentioned that my activity in my dual pane app doesn't really do much apart from loading the left pane fragment and I can't quite see the need for a single activity to ever have to manage hundreds of fragments.

Activity is not restarting on tab changed in android

I am making a activity using Tab-Host.
I have two tabs. When I start the tab-Host activity, the tab-Host opens the activity and the life-cycle of the activity is calling but when I changed the tab and again open that previous tab the activity is not getting its callback methods like resume.
I don't think there is any specific reason it should restart. For changing configuration (like rotating the device or sliding out a keyboard) there is a specific trigger because the app needs to deal with the change. But any other process should go according to the Activitvy lifeCycle
When your app goes to the background (looses focus) for any reason you get onPause() called, and when it goes back, your onResume() will be called. This is the same for when you go home and then back to your app, or when you switch activities like that. No new intent or something like that, just going back to the activity.
You should put your code that needs to run in the onResume().
Do what you need to do in the activity in onResume() instead. That will get called everytime, not just the first time it is created.
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
When you switch from one tab to the other and back, the first tab only gets its onResume method called since it has already had its onCreate called the first time.
You can run the code you like in your onResume method if you want anything specific to happen when it gets focus again.

Categories

Resources