I am using Fragments as Tabs in my application in an Activity that is extended from FragmnetActivity. I am able to add initial Fragments and then on the basis of my application settings, I am replacing fragments. When I am in the debug mode, I observe that, onCreate and other overriden methods of the very new fragmnet are being called twice. Why so? and How can I restrict them to be called once only.
Following is the way I am using Fragments in my app:
public class FragmentTabs extends FragmentActivity implements OnTabChangeListener {
private FragmentTabHost mTabHost;
private HomeFragment homeFragmnet;
private GroupFragment groupFragment;
private TemplateFragment templateFragment;
private SetingsFragment settingsFragment;
private CalendarViewFragment calendarViewFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.fragment_tabs);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
homeFragmnet = new HomeFragment();
groupFragment = new GroupFragment();
templateFragment = new TemplateFragment();
settingsFragment = new SetingsFragment();
calendarViewFragment = new CalendarViewFragment();
mTabHost.setOnTabChangedListener(this);
if (Database.getSharedObject(getApplicationContext()).getAppSettings().getListView() == 1) {
mTabHost.addTab(mTabHost.newTabSpec("home").setIndicator("", getResources().getDrawable(R.drawable.home_tab)), HomeFragment.class, null);
} else {
mTabHost.addTab(mTabHost.newTabSpec("home").setIndicator("", getResources().getDrawable(R.drawable.home_tab)), CalendarViewFragment.class, null);
}
mTabHost.addTab(mTabHost.newTabSpec("groups").setIndicator("", getResources().getDrawable(R.drawable.groups_tab)), GroupFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("templates").setIndicator("", getResources().getDrawable(R.drawable.templates_tab)),TemplateFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("settings").setIndicator("", getResources().getDrawable(R.drawable.settings_tab)), SetingsFragment.class, null);
}
#Override
protected void onResume() {
super.onResume();
}
private void showHomeFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.realtabcontent, homeFragmnet);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.disallowAddToBackStack();
ft.commit();
}
private void showGroupsFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.realtabcontent, groupFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.disallowAddToBackStack();
ft.commit();
}
private void showTemplateFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.realtabcontent, templateFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.disallowAddToBackStack();
ft.commit();
}
private void showSettingsFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.realtabcontent, settingsFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.disallowAddToBackStack();
ft.commit();
}
private void showCalendarViewFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.realtabcontent, calendarViewFragment);
ft.disallowAddToBackStack();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
#Override
public void onTabChanged(String arg0) {
if (mTabHost.getCurrentTab() == 0) {
if (Database.getSharedObject(getApplicationContext()).getAppSettings().getListView() == 1) {
showHomeFragment();
} else {
showCalendarViewFragment();
}
} else if (mTabHost.getCurrentTab() == 1) {
showGroupsFragment();
} else if (mTabHost.getCurrentTab() == 2) {
showTemplateFragment();
} else if (mTabHost.getCurrentTab() == 3) {
showSettingsFragment();
}
}
Any help is appreciated. Thanks!
I use show() and hide() instead, and it works well.
private void showHomeFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (homeFragmnet.isAdded())
ft.show(homeFragmnet);
else
ft.add(R.id.realtabcontent, homeFragmnet);
if (groupFragment.isAdded()) ft.hide(groupFragment);
if (templateFragment.isAdded()) ft.hide(templateFragment);
if (settingsFragment.isAdded()) ft.hide(settingsFragment);
if (calendarViewFragment.isAdded()) ft.hide(calendarViewFragment);
ft.commit();
}
Related
When i change tab of Bottom Bar for example when the home tab is selected and when i change the tab and select category tab in first time load data and it is not problem but when select again home tab again reload fragment and load data again.
how to resolve this problem and save state fragment.
My code:
bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(int tabId) {
displayFragment(tabId);
}
});
private void displayFragment(int id) {
Fragment selectedFragment = null;
switch (id) {
case R.id.tab_home:
selectedFragment = HomeFragment.getInstance();
break;
case R.id.tab_category:
selectedFragment = CategoryFragment.getInstace();
break;
}
if (selectedFragment != null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.contentContainer, selectedFragment);
transaction.commit();
}
}
There are multiple ways you can handle preserving and updating your fragments data throughout its life cycle. I would look into the lifecycle of activity fragments to better grasp what applies to your context. From 30k feet, after you call .replace() the fragment's override onCreateView() should fire, here you can handle your update logic.
As I mentioned, context is big here. If you end up changing your transaction logic, it could impact the life cycle of your fragments. For example, if you were hiding/showing your fragments, using the override onHidden() or onResume() could be a better solution.
In addition, you also should consider how your navigation logic impacts and interacts with your activity's/fragment's backstack. In your current logic, you're creating a new instance of the fragment each time a tab is selected.
This is answer my question :
public class MainActivity extends AppCompatActivity {
FeedFragment feedFragment;
PublishFragment publishFragment;
ServicesFragment servicesFragment;
SearchFragment searchFragment;
ProfileFragment profileFragment;
FragmentTransaction ft;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomBar bottomBar = (BottomBar) findViewById(R.id.bottomBar);
feedFragment = new FeedFragment();
publishFragment = new PublishFragment();
servicesFragment = new ServicesFragment();
searchFragment = new SearchFragment();
profileFragment = new ProfileFragment();
bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(#IdRes int tabId) {
if (tabId == R.id.feed_icon) {
GeneralUtils.logPrint("feed");
ft = getSupportFragmentManager().beginTransaction();
if (feedFragment.isAdded()) {
ft.show(feedFragment);
} else {
ft.add(R.id.fragment_container, feedFragment);
}
hideFragment(ft,publishFragment);
hideFragment(ft, servicesFragment);
hideFragment(ft,searchFragment);
hideFragment(ft,profileFragment);
ft.commit();
}
if (tabId == R.id.publish_icon) {
GeneralUtils.logPrint("publish");
ft = getSupportFragmentManager().beginTransaction();
if (publishFragment.isAdded()) {
ft.show(publishFragment);
} else {
ft.add(R.id.fragment_container, publishFragment);
}
hideFragment(ft,feedFragment);
hideFragment(ft, servicesFragment);
hideFragment(ft,searchFragment);
hideFragment(ft,profileFragment);
ft.commit();
}
if (tabId == R.id.services_icon) {
GeneralUtils.logPrint("services");
ft = getSupportFragmentManager().beginTransaction();
if (servicesFragment.isAdded()) {
ft.show(servicesFragment);
} else {
ft.add(R.id.fragment_container, servicesFragment);
}
hideFragment(ft,feedFragment);
hideFragment(ft, publishFragment);
hideFragment(ft,searchFragment);
hideFragment(ft,profileFragment);
ft.commit();
}
if (tabId == R.id.search_icon) {
GeneralUtils.logPrint("search");
ft = getSupportFragmentManager().beginTransaction();
if (searchFragment.isAdded()) {
ft.show(searchFragment);
} else {
ft.add(R.id.fragment_container, searchFragment);
}
hideFragment(ft,feedFragment);
hideFragment(ft,publishFragment);
hideFragment(ft,servicesFragment);
hideFragment(ft,profileFragment);
ft.commit();
}
if (tabId == R.id.profile_icon) {
GeneralUtils.logPrint("profile");
ft = getSupportFragmentManager().beginTransaction();
if (profileFragment.isAdded()) {
ft.show(profileFragment);
} else {
ft.add(R.id.fragment_container, profileFragment);
}
hideFragment(ft,feedFragment);
hideFragment(ft, publishFragment);
hideFragment(ft,servicesFragment);
hideFragment(ft,searchFragment);
ft.commit();
}
}
});
}
private void hideFragment(FragmentTransaction ft, Fragment f) {
if (f.isAdded()) {
ft.hide(f);
}
}
}
I am working on single activity based principle. But I am facing a problem when the same fragment is open again because its again adds in fragment backstack entry. So backstack contains multiple backstack entries for same fragment. This creates problem on back navigation.
Example :- A|B|C|D|A|C|A
So when I press back key same fragment is displaying multiple times. Is there any way to reuse the existing fragment from backstack entry.
I am managing my backstack like this :-
fragmentManager.beginTransaction().setCustomAnimations(R.anim.fragment_enter,
R.anim.fragment_exit, R.anim.pop_enter, R.anim.pop_exit).
add(R.id.frameLayout, fragment).addToBackStack(backStateName).commit();
Any kind of help will be appreciated.
private void createOrResumeFragment(String fragmentTag){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
boolean fragmentPopped = manager.popBackStackImmediate (fragmentTag, 0);
Fragment fragment = manager.findFragmentByTag(fragmentTag);
if(!fragmentPopped && fragment == null){
//Create an new instance if it is null and add it to stack
fragment = new MyFragment();
ft.addToBackStack(fragmentTag);
}
ft.replace(R.id.framelayout, fragment);
ft.commit();
}
Trying this using the fragment list
See the Answer Here
Initialize the fragments list
static List<String> fragments = new ArrayList<String>();
on Start of first fragment on Activity add this
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.frame, new AFragment()).commit();
fragments.add("package.fragment.AFragment");
}
Code to fragment change and take in back stack
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
//fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
if(!fragments.contains(backStateName)) {
// ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
ft.replace(R.id.frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
fragments.add(backStateName);
System.out.println("backStateName" + fragments);
}
else
{
ft.replace(R.id.frame, fragment);
ft.commit();
}
onBackpressed
#Override
public void onBackPressed() {
if(fragments.size()>0)
{
fragments.remove(fragments.size()-1);
}
super.onBackPressed();
}
for back remove stack
final android.app.FragmentManager fm = getFragmentManager();
fm.addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() ==0) {
// dLayout.closeDrawers();
finish();
}
else
{
// dLayout.closeDrawers();
}
}
});
Before adding or replacing the fragment on backstack, check that if the fragment already in backstack or not.
boolean fragmentPopped = fragmentManager.popBackStackImmediate(backStateName, 0);
if (fragmentPopped) {
// fragment is popped from backStack
} else {
// add or replace your fragment here
}
public void changeFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentVisibleFragment = fragmentManager.findFragmentById(R.id.container);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, fragment, fragment.getClass().getSimpleName());
if (!currentVisibleFragment.getClass().getSimpleName().trim().equalsIgnoreCase(fragment.getClass().getSimpleName().trim())) {
for (int i = fragmentManager.getBackStackEntryCount() - 1; i > 0; i--) {
if (fragmentManager.getBackStackEntryAt(i).getName().equalsIgnoreCase(fragment.getClass().getSimpleName())) {
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(i).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
fragmentTransaction.addToBackStack(fragment.getClass().getSimpleName());
} else {
fragmentManager.popBackStack();
fragmentTransaction.addToBackStack(fragment.getClass().getSimpleName());
}
fragmentTransaction.commit();
}
boolean doubleBackToExitPressedOnce = false;
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
super.onBackPressed();
} else {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
finish();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Are you sure you want to exit?", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
}
Call the method to replace fragment with single entry in backstack
changeFragment(new YourFragmentClassName());
I'm developing a kiosk app where people can walk to and order something.
I have a single activity with bunch of different fragments (order, review, pay, etc). Some replace each other, and some get added. The activity has a single fragment hardcoded R.id.fragmentContainer and the rest are programmatically added and tagged.
Now what I want is to have a function in my activity that calls one of the elements of the fragments (look at updateReceivedData()) but for some reason I'm not able to do so and I get cannot resolve method adjustPriceFunc.
I'm adding the code so someone could tell me what I'm doing wrong. The app would normally talk to some hardware so I took out a bunch of those details from the code to make it easier to read.
public class MainActivity extends FragmentActivity {
private final String TAG = MainActivity.class.getSimpleName();
List<WeakReference<Fragment>> fragList = new ArrayList<WeakReference<Fragment>>();
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.backbone);
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
android.support.v4.app.Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = new Fragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, fragment, "SystemDownFragment")
.addToBackStack(null)
.commit();
}
}
public void orderFunc() {
Log.d(TAG, "orderFunc()");
if(sendingLogFlag) attemptSend(TAG + ":orderFunc()");
for(int i = 0; i < getActiveFragments().size(); i++) {
getSupportFragmentManager().beginTransaction().remove(getActiveFragments().get(i)).commit();
}
Fragment newFragment = new Fragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragmentContainer, newFragment, "OrderFragment");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
public void checkoutFunc() {
Log.d(TAG, "checkoutFunc()");
if(sendingLogFlag) attemptSend(TAG + ":checkoutFunc()");
for(int i = 0; i < getActiveFragments().size(); i++) {
getSupportFragmentManager().beginTransaction().remove(getActiveFragments().get(i)).commit();
}
Fragment newFragment = new Fragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragmentContainer, newFragment, "CheckOutFragment");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
public void reviewFunc(){
Log.d(TAG, "reviewFunc()");
if(sendingLogFlag) attemptSend(TAG + ":reviewFunc()");
if(getActiveFragments().size() > 1){
Fragment frag = getSupportFragmentManager().findFragmentByTag("ReviewFragment");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
ft.remove(frag);
ft.commit();
}
else {
Fragment newFragment = new Fragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.add(R.id.fragmentContainer, newFragment, "ReviewFragment");
ft.commit();
}
getSupportFragmentManager().executePendingTransactions();
}
public void payFunc(boolean enabled){
Log.d(TAG, "payFunc()");
if(sendingLogFlag) attemptSend(TAG + ":payFunc()");
if(!enabled){
Fragment frag = getSupportFragmentManager().findFragmentByTag("PayFragment");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
ft.remove(frag);
ft.commit();
}
else {
Fragment newFragment = new Fragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.add(R.id.fragmentContainer, newFragment, "PayFragment");
ft.commit();
}
getSupportFragmentManager().executePendingTransactions();
}
public void doneFunc() {
Log.d(TAG, "doneFunc()");
for(int i = 0; i < getActiveFragments().size(); i++) {
getSupportFragmentManager().beginTransaction().remove(getActiveFragments().get(i)).commit();
}
Fragment newFragment = new Fragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.add(R.id.fragmentContainer, newFragment, "StartupFragment");
ft.commit();
}
#Override
public void onAttachFragment (Fragment fragment) {
fragList.add(new WeakReference(fragment));
}
public List<Fragment> getActiveFragments() {
ArrayList<Fragment> ret = new ArrayList<Fragment>();
for(WeakReference<Fragment> ref : fragList) {
Fragment f = ref.get();
if(f != null) {
if(f.isVisible()) {
ret.add(f);
}
}
}
return ret;
}
private void updateReceivedData() {
Fragment frag = getSupportFragmentManager().findFragmentByTag("PayFragment");
frag.adjustPriceFunc();
}
You are trying to use method adjustPriceFunc() from class Fragment, which is not part of it.
Use this code, where MyFragment is your proper fragment (I assume it should be PayFragment).
private void updateReceivedData() {
Fragment frag = getSupportFragmentManager().findFragmentByTag("PayFragment");
if (frag instanceof MyFragment) {
frag.adjustPriceFunc();
}
}
There is few mistakes here in the code
In orderFunc, checkoutFunc etc. add remove to the transaction and call commit once after the loop, like
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
for(int i = 0; i < getActiveFragments().size(); i++) {
transaction.remove(getActiveFragments().get(i));
}
transaction.commit();
You get compilation error in updateReceivedData because Fragmentdoes not have adjustPriceFunc() method. You need either (cleaner approach) create interface with adjustPriceFunc() method, let your fragment implement it and then your updateReceivedData will look like follows:
private void updateReceivedData() {
InterfaceWithAdjustPriceMethod frag = (InterfaceWithAdjustPriceMethod) getSupportFragmentManager().findFragmentByTag("PayFragment");
frag.adjustPriceFunc();
}
Storing reference to fragment is a bad practice, even if it is WeakReference.
Better use this way:
Fragment fragment = getSupportFragmentManager().findFragmentByTag("tag");
I'm getting this error while trying to launch a Fragment from a first Fragment :
java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()' on a null object reference
Here's the method where I'm getting the error :
#Override
public void onClick(View v) {
Fragment fragment = new PropertyFragment();
if (fragment != null) {
FragmentManager fragmentManager = fragment.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
fragmentTransaction.replace(R.id.rent_viewer, fragment);
fragmentTransaction.addToBackStack(null);
// Commit the transaction
fragmentTransaction.commit();
}
}
Precisely, the following code instruction is causing the error :
fragmentManager.beginTransaction();
Here's how the class and the nested class look like :
public class RentFragment extends Fragment {
...
#SuppressWarnings("unused")
private OnRentFragmentInteractionListener mListener;
public RentFragment() {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnRentFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnRentFragmentInteractionListener");
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_rent, container, false);
myOnClickListener = new RentOnClickListener(getActivity());
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnRentFragmentInteractionListener {
public void onRentFragmentInteraction(Uri uri);
}
private static class RentOnClickListener implements View.OnClickListener {
private final Context context;
private RentOnClickListener(Context context) {
this.context = context;
}
#Override
public void onClick(View v) {
Fragment fragment = new PropertyFragment();
if (fragment != null) {
FragmentManager fragmentManager = fragment.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
fragmentTransaction.replace(R.id.rent_viewer, fragment);
fragmentTransaction.addToBackStack(null);
// Commit the transaction
fragmentTransaction.commit();
}
}
}
}
FragmentManager will be null until it is attached to the activity.So use below code ,
If it is a nested Fragment use this.getChildFragmentManager() for your fragment class else use getActivity().getFragmentManager() or getActivity().getSupportFragmentManager().
Declare your FragmentTransaction and initialize it like this
FragmentTransaction fm;
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
fm = getFragmentManager();
}
Then on your code, you can call this
Fragment fragment = new PropertyFragment();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.rent_viewer, fragment).addToBackStack(null).commit();;
Use the Customize Method in Base Class and use it.
public void replaceFragment(Fragment newFragment, Bundle bundle, boolean isAddToBackStack) {
String tag = newFragment.getClass().getSimpleName();
if (bundle != null) {
newFragment.setArguments(bundle);
}
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (getCurrentFragment() != null) {
ft.hide(getCurrentFragment());
}
ft.add(R.id.frameContainer, newFragment, tag);
newFragment.setRetainInstance(true);
if (isAddToBackStack) {
ft.addToBackStack(tag);
}
try {
ft.commitAllowingStateLoss();
} catch (Exception ex) {
ex.printStackTrace();
// ft.commitAllowingStateLoss();
}
}
You have to set context of activity as shown below on code HomeActivity.this.getSupportFragmentManager();
private Fragment fragment;
private FragmentManager fragmentManager;
fragmentManager=HomeActivity.this.getSupportFragmentManager();
transaction = fragmentManager.beginTransaction();
transaction.add(R.id.main_container, new ProfileFragment()).commit();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
fragmentTransaction.replace(R.id.rent_viewer, fragment);
fragmentTransaction.addToBackStack(null);
// Commit the transaction
fragmentTransaction.commit();
How can I attach existing fragment, when change back tab in ActionBar.NAVIGATION_MODE_TABS?
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.detach(fragment);
}
}
You can verify if your fragment was loaded previously in the fragment stack. Also could store all your used fragments to reuse it
public void setFragment(Fragment fragmentInstance) {
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
Fragment oldFragmentInstance = fragmentManager
.findFragmentById(R.id.curr_fragment);
boolean onlyAttach = false;
List<Fragment> prevFragments = getSupportFragmentManager()
.getFragments();
for (Fragment fragment : prevFragments) {
if (fragment == null) {
continue;
}
if (fragment.getClass().equals(fragmentInstance.getClass())) {
onlyAttach = true;
fragmentInstance = fragment;
break;
}
}
fragmentTransaction.detach(oldFragmentInstance);
if (onlyAttach) {
fragmentTransaction.attach(fragmentInstance);
} else {
fragmentTransaction.replace(R.id.curr_fragment,
fragmentInstance);
fragmentTransaction.addToBackStack(null);
}
try {
fragmentTransaction.commit();
}
}
Hope this helps