android listfragment created twice - android

Here is code where my fragment is created:
if (savedInstanceState == null) {
// During initial setup, plug in the details fragment.
FlightListFragment listFragment =
FlightListFragment.newInstance(mSearchParams);
getSupportFragmentManager().beginTransaction().add(
android.R.id.content, listFragment).commit();
}
But all fragment methods called twice! OnCreateView, OnActivityCreated, OnStart.
Why?
Thanks.

Is your fragment set to retain instance? it might be possible that you're spawning 2 instances of the fragment
Maybe try adding a call to check something like
if (getSupportFragmentManager.findFragmentByTag("myFragment") != null)
{
FlightListFragment listFragment =
FlightListFragment.newInstance(mSearchParams);
getSupportFragmentManager().beginTransaction().add(
android.R.id.content, listFragment).commit();
}

Related

How can I call a method from nested fragment

I have a fragment(this is one tab of my tabhost) "fragA" inside other fragment "fragB" but I need to call one method of "fragB" from "fragA".
when I do from an activity, I do this:
FragB detailsFragment=(FragB)getSupportFragmentManager().findFragmentById(R.id.detailFragment);
detailsFragment.consultaWS(convertIntWebService(categoria),"Pdf");
please, help me
I could finally solve it this way, in fragA:
FragB parentFragment = (FragB) getChildFragmentManager()
.findFragmentByTag("detallesFragBusqueda");
if (parentFragment != null) {
parentFragment.consultaWS("", "AllPdf");
}
Your activity should facilitate all communication between fragments. Just create a method in your Activity that a fragment can call, which will tell another fragment to do something.
If FragA is inside FragB, you can do the same from within your FragA.
FragB parentFragment = (FragB)getActivity().getSupportFragmentManager().findFragmentById(R.id.detailFragment);
parentFragment.fragmentBMethod();
Read this http://developer.android.com/training/basics/fragments/communicating.html.
This document explains that how can you communicate between Activity and Fragment
and also between 2 Fragments
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_main_container);
if (fragment != null) {
((TabLayoutFragment)fragment).tabClickDisable();
}

Getting a reference to a child Fragment after the parent Fragment has been recreated

Starting Android 4.2, Android supports nested Fragments. The doc doesn't give a lot of explanations regarding nested Fragment lifecycles but from experience, it appears their lifecycle is really similar to "regular" Fragments.
It looks like there is one big difference though: child Fragments are not restored when the parent Fragment onCreate method is called. As a consequence, it seems impossible to save/restore a reference to a particular Fragment:
Using getChildFragmentManager.findFragmentByTag(String) always returns null in parent Fragment onCreate(Bundle) because mActive is null.
Using putFragment/getFragment results in a NullPointerException because getFragment looks for the size of a null mActive ArrayList.
So, my question is quite simple. Is there a correct way to retrieve a reference to a child Fragment in the parent Fragment onCreate method?
I don't think you can in onCreate as the view isn't constructed at that time. You can in onViewCreated() though. The logic I used is:
Check if there is saved state in onViewCreated(), if there is, try to get the child fragment
Then check if the child fragment is null, if it is, add it using the child fragment manager.
By "checking" I mean looking up the fragment by id. I guess by tag should work too.
AFAIK you can't get a child fragment before the view hierarchy is restored or created, but you could do the same at later time, for example in onActivityCreated()
What about setRetainInstanceState(true) on your fragment?
Could it solve your problem? It solved some problems when I have ChildFragments in a Fragment. I only have to keep a reference to the childfragment in the fragment.
But I allways did that in onCreateView(). Not sure if it will work in onCreate()
Or do you mean something completely different?
are u using FragmentPagerAdapter?
if not try FragmentPagerAdapter instead of FragmentStatePagerAdapter
I realised that have some bug when using FragmentStatePagerAdapter when i have 4 level nest.
Sorry my english is poor.
#Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
mFragment1 = getFragmentManager().getFragment(savedInstanceState, STATE_Fragment1);
mFragment2 = getFragmentManager().getFragment(savedInstanceState, STATE_Fragment2);
mFragment3 = getFragmentManager().getFragment(savedInstanceState, STATE_Fragment3);
} else {
mFragment1 = SomeFragment.newInstance("param1");
mFragment2 = SomeFragment.newInstance("param2");
mFragment3 = SomeFragment.newInstance("param3");
}
super.onCreate(savedInstanceState);
mMyPagerAdapter = new MyPagerAdapter(getChildFragmentManager(), mFragment1, mFragment2, mFragment3);
}
#Override
public void onSaveInstanceState(Bundle outState) {
if (mFragment1 != null) {
getFragmentManager().putFragment(outState, STATE_Fragment1,
mFragment1);
}
if (mFragment2 != null) {
getFragmentManager().putFragment(outState, STATE_Fragment2,
mFragment2);
}
if (mFragment3 != null) {
getFragmentManager().putFragment(outState, STATE_Fragment3,
mFragment3);
}
super.onSaveInstanceState(outState);
}

Fragment gets initialized twice when reloading activity with tabs when orientation changes

I have a problem reloading an activity with tabs and fragments when I change the orientation of my device.
Here's the situation:
I have an activity which has 3 tabs in the action bar. Each tab loads a different fragment in a FrameLayout in main view. Everything works fine if I don't change the orientation of the device. But when I do that Android tries to initialize the currently selected fragment twice which produce the following error:
E/AndroidRuntime(2022): Caused by: android.view.InflateException: Binary XML file line #39: Error inflating class fragment
Here's the sequence of steps that produce the error:
I load the activity, select tab nr 2. and change the orientation of the device.
Android destroys the activity and the instance of the fragment loaded by tab nr 2 (from now on, 'Fragment 2'). Then it proceeds to create new instances of the activity and the fragment.
Inside Activity.onCreate() I add the first tab to the action bar. When I do that, this tab gets automatically selected. It may represent a problem in the future, but I don't mind about that now. onTabSelected gets called and a new instance of the first fragment is created and loaded (see code below).
I add all the other tabs without any event being triggered, which is fine.
I call ActionBar.selectTab(myTab) to select Tab nr 2.
onTabUnselected() gets called for the first tab, and then onTabSelected() for the second tab. This sequence replaces the current fragment for an instance of Fragment 2 (see code below).
Next, Fragment.onCreateView() is called on Fragment 2 instance and the fragment layout gets inflated.
Here is the problem. Android Calls onCreate() and then onCreateView() on the fragment instance ONCE AGAIN, which produces the exception when I try to inflate (a second time) the layout.
Obviously the problem is Android is initializing the fragment twice, but I don't know why.
I tried NOT selecting the second tab when I reaload the activity but the second fragment gets initialized anyway and it is not shown (since I didn't select its tab).
I found this question: Android Fragments recreated on orientation change
The user asks basically the same I do, but I don't like the chosen answer (it's only a workaroud). There must be some way to get this working without the android:configChanges trick.
In case it's not clear, what I want to know how whether to prevent the recreation of the fragment or to avoid the double initialization of it. It would be nice to know why is this happening also. :P
Here is the relevant code:
public class MyActivity extends Activity implements ActionBar.TabListener {
private static final String TAG_FRAGMENT_1 = "frag1";
private static final String TAG_FRAGMENT_2 = "frag2";
private static final String TAG_FRAGMENT_3 = "frag3";
Fragment frag1;
Fragment frag2;
Fragment frag3;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// my_layout contains a FragmentLayout inside
setContentView(R.layout.my_layout);
// Get a reference to the fragments created automatically by Android
// when reloading the activity
FragmentManager fm = getFragmentManager();
this.frag1 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_1);
this.frag2 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_2);
this.frag3 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_3)
ActionBar actionBar = getActionBar();
// snip...
// This triggers onTabSelected for the first tab
actionBar.addTab(actionBar.newTab()
.setText("Tab1").setTabListener(this)
.setTag(MyActivity.TAG_FRAGMENT_1));
actionBar.addTab(actionBar.newTab()
.setText("Tab2").setTabListener(this)
.setTag(MyActivity.TAG_FRAGMENT_2));
actionBar.addTab(actionBar.newTab()
.setText("Tab3").setTabListener(this)
.setTag(MyActivity.TAG_FRAGMENT_3));
Tab t = null;
// here I get a reference to the tab that must be selected
// snip...
// This triggers onTabUnselected/onTabSelected
ab.selectTab(t);
}
#Override
protected void onDestroy() {
// Not sure if this is necessary
this.frag1 = null;
this.frag2 = null;
this.frag3 = null;
super.onDestroy();
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Fragment curFrag = getFragmentInstanceForTag(tab.getTag().toString());
if (curFrag == null) {
curFrag = createFragmentInstanceForTag(tab.getTag().toString());
if(curFrag == null) {
// snip...
return;
}
}
ft.replace(R.id.fragment_container, curFrag, tab.getTag().toString());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
Fragment curFrag = getFragmentInstanceForTag(tab.getTag().toString());
if (curFrag == null) {
// snip...
return;
}
ft.remove(curFrag);
}
private Fragment getFragmentInstanceForTag(String tag)
{
// Returns this.frag1, this.frag2 or this.frag3
// depending on which tag was passed as parameter
}
private Fragment createFragmentInstanceForTag(String tag)
{
// Returns a new instance of the fragment requested by tag
// and assigns it to this.frag1, this.frag2 or this.frag3
}
}
The code for the Fragment is irrelevant, it just returns an inflated view on onCreateView() method override.
I got a simple answer for that:
Just add setRetainInstance(true); to the Fragment's onAttach(Activity activity) or onActivityCreated(Bundle savedInstanceState).
These two are call-backs in the Fragment Class.
So basically, what setRetainInstance(true) does is:
It maintains the state of your fragment as it is, when it goes through:
onPause();
onStop();
It maintains the instance of the Fragment no matter what the Activity goes through.
The problem with it could be, if there are too many Fragments, it may put a strain on the System.
Hope it helps.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
setRetainInstance(true);
}
Open for Correction as always. Regards, Edward Quixote.
It seems that, when the screen is rotated and the app restarted, it is recreating each Fragment by calling the default constructor for the Fragment's class.
I have encountered the same issue and used the following workaround:
in the fragment's onCreateView begining of:
if (mView != null) {
// Log.w(TAG, "Fragment initialized again");
((ViewGroup) mView.getParent()).removeView(mView);
return mView;
}
// normal onCreateView
mView = inflater.inflate(R.layout...)
I think this is a fool proof way to avoid re-inflating of the root view of the fragment:
private WeakReference<View> mRootView;
private LayoutInflater mInflater;
/**
* inflate the fragment layout , or use a previous one if already stored <br/>
* WARNING: do not use in any function other than onCreateView
* */
private View inflateRootView() {
View rootView = mRootView == null ? null : mRootView.get();
if (rootView != null) {
final ViewParent parent = rootView.getParent();
if (parent != null && parent instanceof ViewGroup)
((ViewGroup) parent).removeView(rootView);
return rootView;
}
rootView = mFadingHelper.createView(mInflater);
mRootView = new WeakReference<View>(rootView);
return rootView;
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
mInflater=inflater!=null?inflater:LayoutInflater.from(getActivity());
final View view = inflateRootView();
... //update your data on the views if needed
}
add
android:configChanges="orientation|screenSize"
in the manifest file
To protect activity recreate try to add configChanges in your Activity tag (in manifest), like:
android:configChanges="keyboardHidden|orientation|screenSize"
My code was a little different, but I believe our problem is the same.
In the onTabSelected I didn't use replace, I use add when is the first time creating the fragment and attach if isn't. In the onTabUnselected I use detach.
The problem is that when the view is destroyed, my Fragment was attached to the FragmentManager and never destroyed. To solve that I implemented on the onSaveInstanceBundle to detach the fragment from the FragmentManager.
The code was something like that:
FragmentTransition ft = getSupportFragmentManager().begin();
ft.detach(myFragment);
ft.commit();
In the first try I put that code in the onDestroy, but I get a exception telling me that I couldn't do it after the onSaveInstanceBundle, so I moved the code to the onSaveInstanceBundle and everything worked.
Sorry but the place where I work don't allow me to put the code here on StackOverflow. This is what I remember from the code. Feel free to edit the answer to add the code.
I think you are facing what I faced. I had a thread downloader for json which starts in onCreate() , each time I changed the orientation the thread is called and download is fired. I fixed this using onSaveInstance() and onRestoreInstance() to pass the json response in a list, in combination of checking if the list is not empty, so the extra download is not needed.
I hope this gives you a hint.
I solved this problem by using below code.
private void loadFragment(){
LogUtil.l(TAG,"loadFragment",true);
fm = getSupportFragmentManager();
Fragment hf = fm.findFragmentByTag("HOME");
Fragment sf = fm.findFragmentByTag("SETTING");
if(hf==null) {
homeFragment = getHomeFragment();// new HomeFragment();
settingsFragment = getSettingsFragment();// new Fragment();
fm.beginTransaction().add(R.id.fm_place, settingsFragment, "SETTING").hide(settingsFragment).commit();
fm.beginTransaction().add(R.id.fm_place, homeFragment, "HOME").commit();
activeFragment = homeFragment;
}else{
homeFragment = hf;
settingsFragment = sf;
activeFragment = sf;
}
}
Initiate this method in OnCreate();

Android: on screen orientation change fragment.getActivity is null

I'll try to explain my problem:
all my fragments are using setRetainInstance(true)
In my activity onCreate I'm doing this:
if (savedInstanceState == null) {
fragment = onCreatePane();
fragment.setArguments(intentToFragmentArguments(getIntent()));
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.add(R.id.root_container, fragment, getFragmentTag());
trans.commit();
} else {
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
if ( fragment == null ) {
fragment = getSupportFragmentManager().findFragmentByTag(getFragmentTag());
}
if (fragment == null) {
fragment = onCreatePane();
fragment.setArguments(intentToFragmentArguments(getIntent()));
}
trans.add(R.id.root_container, fragment, getFragmentTag());
trans.commit();
}
So when I create the activity and savedInstance is null I create the Fragment, I set it's arguments, I begin the transaction and add my fragment to the transaction with it's own tag (to get it back later).
The user interact with the activity and change the orientation. The activity is destroyed and recreated (as normal activity lifelycle). So now it enter the else, the fragment is null and I do a fragment = getSupportFragmentManager().findFragmentByTag(getFragmentTag()); that returns the correct Fragment holded by the fragmentManager.
The problem is that this fragment hold a reference to the old Activity that has been destoyed so if I do a fragment.getActivity it returns null. How can I update the fragment reference to the acitivy to the new re-created Activity?
UPDATE: To be more precise I'm on the SearchActivity that call the onNewIntent when it get a new Search. So the actual interaction is this-> user do a search -> search is displayed correctly -> user change orientation, result is displayed correctly (if user interact with results they are fine) -> user do a new search from the search button and this call the SearchActivity's onNewIntent that dispatch the new intent to the fragment that has the search logic. Here it crashes because the reference to the activity is null
When and where are you calling getActivity()? The activity reference does get updated automatically, but not immediately. You should be safe to access it after onActivityCreated() was called.
just remove null check from else part if ( fragment == null ) { fragment = getSupportFragmentManager( ...... let update fragment with new one created on orientation change ......
If setRetainInstance(true) -- yes, it's the solution (to find fragment by tag, because instantiate it again -- is the wrong way -- there could be background routines in progress). Otherwise, if you have setRetainInstance(false) the problem can be back.
I had the similar one. I my case -- because I used Loader (in background). Solution was simple: to destroy fragment's loaders in onDestroy() method of the fragment.
In your baseAcvivity you can override onSaveInstanceStat to resolve this problem :
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//solution of fragment.getActivity() is null
outState.remove("android:support:fragments");
}

How do I get the currently displayed fragment?

I am playing with fragments in Android.
I know I can change a fragment by using the following code:
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();
MyFragment myFragment = new MyFragment(); //my custom fragment
fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();
My question is, in a Java file, how can I get the currently displayed Fragment instance?
When you add the fragment in your transaction you should use a tag.
fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");
...and later if you want to check if the fragment is visible:
MyFragment myFragment = (MyFragment)getSupportFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
// add your code here
}
See also http://developer.android.com/reference/android/app/Fragment.html
I know it's an old post, but was having trouble with it previously too. Found a solution which was to do this in the onBackStackChanged() listening function
#Override
public void onBackPressed() {
super.onBackPressed();
Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
if(f instanceof CustomFragmentClass)
// do something with f
((CustomFragmentClass) f).doSomething();
}
This worked for me as I didn't want to iterate through every fragment I have to find one that is visible.
Here is my solution which I find handy for low fragment scenarios
public Fragment getVisibleFragment(){
FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
List<Fragment> fragments = fragmentManager.getFragments();
if(fragments != null){
for(Fragment fragment : fragments){
if(fragment != null && fragment.isVisible())
return fragment;
}
}
return null;
}
Every time when you show fragment you must put it tag into backstack:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
And then when you need to get current fragment you may use this method:
public BaseFragment getActiveFragment() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
return null;
}
String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
Kotlin way;
val currentFragment = supportFragmentManager.fragments.last()
What I am using to find current displaying fragment is in below code. It is simple and it works for me by now. It runs in the activity which holds the fragments
FragmentManager fragManager = this.getSupportFragmentManager();
int count = this.getSupportFragmentManager().getBackStackEntryCount();
Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
The reactive way:
Observable.from(getSupportFragmentManager().getFragments())
.filter(fragment -> fragment.isVisible())
.subscribe(fragment1 -> {
// Do something with it
}, throwable1 -> {
//
});
My method is based on try / catch like this :
MyFragment viewer = null;
if(getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT) instanceOf MyFragment){
viewer = (MyFragment) getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT);
}
But there may be a better way ...
If you are using the AndroidX Navigation:
val currentFragment = findNavController(R.id.your_navhost)?.currentDestination
For more info on this navigation component:
https://developer.android.com/guide/navigation/navigation-getting-started
Well, this question got lots of views and attention but still did not contained
the easiest solution from my end - to use getFragments().
List fragments = getSupportFragmentManager().getFragments();
mCurrentFragment = fragments.get(fragments.size() - 1);
You can query which fragment is loaded into your Activities content frame, and retrieve the fragment class, or fragment 'simple name' (as a string).
public String getCurrentFragment(){
return activity.getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
}
Usage:
Log.d(TAG, getCurrentFragment());
Outputs:
D/MainActivity: FragOne
If get here and you are using Kotlin:
var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
R.id.fragment_container is the id where the fragment is presenting on their activity
Or if you want a nicer solution:
supportFragmentManager.findFragmentById(R.id.content_main)?.let {
// the fragment exists
if (it is FooFragment) {
// The presented fragment is FooFragment type
}
}
It's a bit late, But for anyone who is interested :
If you know the index of the your desired fragment in FragmentManager just get a reference to it and check for isMenuVisible() function! here :
getSupportFragmentManager().getFragments().get(0).isMenuVisible()
If true Its visible to user and so on!
1)
ft.replace(R.id.content_frame, fragment, **tag**).commit();
2)
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);
3)
if (currentFragment.getTag().equals(**"Fragment_Main"**))
{
//Do something
}
else
if (currentFragment.getTag().equals(**"Fragment_DM"**))
{
//Do something
}
There's a method called findFragmentById() in SupportFragmentManager. I use it in the activity container like :
public Fragment currentFragment(){
return getSupportFragmentManager().findFragmentById(R.id.activity_newsfeed_frame);
}
That's how to get your current Fragment. If you have custom Fragment and need to check what Fragment it is, I normally use instanceof :
if (currentFragment() instanceof MyFrag){
// Do something here
}
This should work -
val visibleFragment = supportFragmentManager.fragments.findLast { fgm -> fgm.isVisible }
Timber.d("backStackIterator: visibleFragment: $visibleFragment")
Inspired by Tainy's answer, here is my two cents. Little modified from most other implementations.
private Fragment getCurrentFragment() {
FragmentManager fragmentManager = myActivity.getSupportFragmentManager();
int stackCount = fragmentManager.getBackStackEntryCount();
if( fragmentManager.getFragments() != null ) return fragmentManager.getFragments().get( stackCount > 0 ? stackCount-1 : stackCount );
else return null;
}
Replace "myActivity" with "this" if it is your current activity or use reference to your activity.
This is simple way to get current fragment..
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override public void onBackStackChanged() {
currentFragment = fragmentManager.findFragmentById(R.id.content);
if (currentFragment != null && (currentFragment instanceof LoginScreenFragment)) {
logout.setVisibility(View.GONE);
} else {
logout.setVisibility(View.VISIBLE);
}
}
});
Checkout this solution. It worked for me to get the current Fragment.
if(getSupportFragmentManager().getBackStackEntryCount() > 0){
android.support.v4.app.Fragment f =
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if(f instanceof ProfileFragment){
Log.d(TAG, "Profile Fragment");
}else if(f instanceof SavedLocationsFragment){
Log.d(TAG, "SavedLocations Fragment");
}else if(f instanceof AddLocationFragment){
Log.d(TAG, "Add Locations Fragment");
}
it's so simple, not that much code you need to write
yourFragment.isAdded()
or
yourFragment.isVisible();
I prefer isAdded(),both of them return boolean value use it in if condition and must initialize your fragment in onCreate() otherwise you will get null point exception.
None of the above 30 answers fully worked for me. But here is the answer that worked:
Using Kotlin, when using Navigation Component:
fun currentVisibleFragment(): Fragment? {
return supportFragmentManager.fragments.first()?.getChildFragmentManager()?.getFragments()?.get(0)
}
Sev's answer works for when you hit the back button or otherwise change the backstack.
I did something slightly different, though. I have a backstack change listener setup on a base Fragment and its derived fragments and this code is in the listener:
Fragment f = getActivity().getSupportFragmentManager().findFragmentById(R.id.container);
if (f.getClass().equals(getClass())) {
// On back button, or popBackStack(),
// the fragment that's becoming visible executes here,
// but not the one being popped, or others on the back stack
// So, for my case, I can change action bar bg color per fragment
}
Easy way to do that :
Fragment fr=getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String fragmentName = fr.getClass().getSimpleName();
I had to do this very recently
public Fragment getCurrentFragment() {
return fragmentManager.findFragmentById(R.id.container);
}
and finaly i got last fragment on this container.
final FragmentManager fm=this.getSupportFragmentManager();
final Fragment fragment=fm.findFragmentByTag("MY_FRAGMENT");
if(fragment != null && fragment.isVisible()){
Log.i("TAG","my fragment is visible");
}
else{
Log.i("TAG","my fragment is not visible");
}
If you are getting the current instance of Fragment from the parent activity you can just
findFragmentByID(R.id.container);
This actually get's the current instance of fragment that's populated on the view. I had the same issue. I had to load the same fragment twice keeping one on backstack.
The following method doesn't work. It just gets a Fragment that has the tag. Don't waste your time on this method. I am sure it has it's uses but to get the most recent version of the same Fragment is not one of them.
findFragmentByTag()
Kotlin safer way than exposed here
supportFragmentManager.fragments.lastOrNull()?.let { currentFragment ->
//Do something here
}
This is work for me. I hope this will hepl someone.
FragmentManager fragmentManager = this.getSupportFragmentManager();
String tag = fragmentManager
.getBackStackEntryAt(
fragmentManager
.getBackStackEntryCount() - 1)
.getName();
Log.d("This is your Top Fragment name: ", ""+tag);
I found findFragmentByTag isn't that convenient. If you have String currentFragmentTag in your Activity or parent Fragment, you need to save it in onSaveInstanceState and restore it in onCreate. Even if you do so, when the Activity recreated, onAttachFragment will called before onCreate, so you can't use currentFragmentTag in onAttachFragment(eg. update some views based on currentFragmentTag), because it's might not yet restored.
I use the following code:
Fragment getCurrentFragment() {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if(fragments.isEmpty()) {
return null;
}
return fragments.get(fragments.size()-1);
}
The document of FragmentManager state that
The order of the fragments in the list is the order in which they were added or attached.
When you need to do stuff based on current fragment type, just use getCurrentFragment() instance of MyFragment instead of currentFragmentTag.equals("my_fragment_tag").
Note that getCurrentFragment() in onAttachFragment will not get the attaching Fragment, but the previous attached one.
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
Well, I guess this is the most straight forward answer to this question.
I hope this helps.

Categories

Resources