I have four tabs and its four fragments attached. Swiping will take you to next fragment or tab.
All four fragments have the dynamic data from the server.
First time it was loading 1st and 2nd fragments loading. then swiping to right 3rd loading and 1st detaching, but I am in 2nd fragment.
Now, I swipe to left the loading for 3rd fragment not completed. So it was taking more time to load. I am in 1st fragment the background process of 3rd is still running and showing the toast message and all.
How to give preference or detaching the unwanted fragment to overcome this problem.
Or can you give some good suggestions to this problem
As per the stackOverflow answer I did.
https://stackoverflow.com/a/20350313/4675067
boolean Loaded = false;
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && !Loaded ) {
loadLectures();
Loaded = true;
}
}
Related
I have 2 fragments (Fragment A and Fragment B) both with collapsing toolbar layouts and corresponding recyclerviews within a coordinatorlayout.
If I scroll up in my recyclerview (so the CollapsingToolbarLayout has collapsed) and then open Fragment B from fragment A (Pushing A onto the backstack).
When I return to fragment A by hitting back. The CollapsingToolbarLayout/AppBarLayout is always expanded, even though the recycler view is in the same position.
Anyone experience this?
There's a issue related to this.
According to Chris Banes.
Add these lines inside onViewCreated() of your fragment to solve the issue.
ViewCompat.requestApplyInsets(mCoordinatorLayout);
It's an old question but none of the answers it's correct. I found this other question where they fixed the problem:
How to restore Collapsing Toolbar Layout State after screen orientation change
You have to set an id to your views in order to restore their state automatically.
I had face same problem so i write below code:-
private boolean isExpand = true;
private void setTitleNotExpand(boolean isExpand) {
if(getFragmentViewHolder() != null) {
this.isExpand = isExpand;
// AppBarLayout variable
getFragmentViewHolder().appbar.setExpanded(isExpand);
}
}
when you do add back stack then write below code :-
// write below code where you want to stick your toolbar
setTitleNotExpand(false);
// write below code where you want not to stick your toolbar
setTitleNotExpand(true);
on your onFragmentViewHolderCreated write below code :-
getFragmentViewHolder().appbar.setExpanded(isExpand);
another thing to consider is that views cannot restore their state if they don't have an id
Today, to fix this issue you only have to set an id to your coordinator layout to fix this.
I have a main activity that contains a frame layout and 4 tab buttons, and there are in total 4 fragments, each fragment relates to a tab button, depending on which tab button is clicked, the corresponding fragment will be swapped into the frame layout to replace the old one. Now in each of the fragment there's a webview that loads different URL when the fragment is created. My question is how to prevent from the webview to reload every time when fragments swap? Below are the code how I swap my fragment:
FragmentMainPage fragment = new FragmentMainPage();
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.frameLayout, fragment);
transaction.commit();
currentPage = VT_Constants.HOME_PAGE;
Calling replace is destructive: it tears down the fragment's view hierarchy, so when you add it back later, the views have to be rebuilt, which explains the behavior you are seeing.
Try show and hide instead. These maintain the fragment's views, so they can be re-attached to your activity when the user clicks on that fragment's tab. Something like this (although I'm not sure how you want to get the reference to the current fragment):
FragmentMainPage fragment = new FragmentMainPage();
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
Fragment oldFragment = fm.findFragmentByTag(...); // somehow get the current fragment showing
FragmentTransaction transaction = fm.beginTransaction();
transaction.hide(oldFragment);
transaction.show(fragment);
transaction.commit();
You can set page limit.
viewPager.setOffscreenPageLimit(4);
Webviews won't reload anymore.
I was also facing the same problem. Tried changing the webView Settings and none worked for me. This is not the problem with the webview.
The actual problem here is your fragment is a part of ViewPager. By default viewPager will have setOffscreenPageLimit as 1.
For one immediate tab switch, you will not see any refresh of the fragment. Post that you will face this issue.
You have to simply add this one line to your view pager if you don't want to refresh fragments
mViewPager.setOffscreenPageLimit(numOfTabs);
for ex:
mViewPager.setOffscreenPageLimit(10); //if you have 10 tabs
Hope this helps.
I'm trying to understand how to preserve fragment view state when fragments are used within navigation tabs. In my efforts, I've come across two problems that I cannot find any proper solutions to.
I have two tabs, Tab1 and Tab2. Tab1's layout is defined by FragmentA and Tab2's layout is defined by FragmentB.
I've followed the approach given here (edit: documentation has changed since this question was asked).
The first problem: Even though my views have IDs, their states are not fully restored when a fragment is re-attached (after a tab switch rotation). In particular: an EditText with an ID does indeed save its entered text, but it does not save its enabled status. Also, buttons do not save if they are enabled or disabled even though they have IDs. I've found two possible workarounds for this problem:
Use hide()/show() instead of attach()/detach() when switching tabs.
in onPause(), save the current fragment view state in a View instance variable of the fragment via getView(). In onCreateView(Bundle savedInstanceState) check if this field is non-null and if that is the case return the value of this field. This solution seems hacky, and I've been told that it might also introduce a memory leak in my app.
The second problem: Consider the following user interaction:
User starts on Tab1 and does some changes that put the view state of Tab1 in a different state than its default state (and we want the fragment to save this view state through tabswitches and device tilts).
User then goes to Tab2. User then tilts her/his device (still at Tab2).
User then swaps to Tab1 (at the new screen orientation).
Now, the problem is: when the user initially swaps from Tab1 to Tab2, the fragment is detached and thereby its view discarded (even though the fragment instance still lives). When the user then tilts the device, the activity - and thereby both FragmentA and FragmentB associated with it - are destroyed. Since FragmentA at this point does no longer have a view (remember: it was detached), we cannot save the state of its view elements (e.g., what buttons are enabled/disabled) during the call to FragmentA.onSaveInstanceState(Bundle savedInstanceState). How do you recover fragment view state in a situation like this? Is the only viable solution to save every single view element's different status flags as SharedPreferences? This seems way too complicated for such an "everyday job".
Problem 1:
Android does not save your view enabled state by default. It seems only things which are directly influenced by user actions (without additional code) are saved. For a normal View, no information is saved, and for a TextView, of which EditText is a subclass, the entered text is saved (if freezesText is set).
If you want to anything else to be saved, you will have to do it yourself. Here is an question with some answers that show how to implement custom view state saving. You can stick with attach/detach if you follow that approach.
Problem 2:
You are right in that Fragment.onSaveInstanceState(Bundle) can be called after your view has already been destroyed. However, this is not where you should be saving your view state. Android will call View.onSaveInstanceState() right before it destroys your views when detaching a fragment. It saves this state and gives it back to you when you attach the fragment again. This is exactly what happens when you flip between tabs normally with no rotations. Fragment.onSaveInstanceState(Bundle) is not called when detaching. Even if you rotate the device, the view state saved as a result of the detach will persist. If you implement View.onSaveInstanceState() as directed above, your view state will be saved and restored properly, even in the Tab1-Tab2-rotate-Tab1 scenario.
Side note:
The example code in the docs seems to have some problems when you try to rotate. The lifetime of the TabListener is the same as that of the Activity - a new one is created every time you rotate. This means it also loses its internal reference to the fragment, every time you rotate. Added fragments are recreated automatically and so there is no need for the TabListener to try to create a new instance and add it, after rotation. Instead, of the internal reference, it should just try to find the fragment with the appropriate tag in the fragment manager. After rotation it will still exist.
The other problem is with that the selected tab is not saved, but this is noted at the bottom of the example. You could save this in Activity.onSaveInstanceState(Bundle).
private ViewPager viewPager;
viewPager = (ViewPager) findViewById(R.id.pager);
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
Setup: My Flex application is one consisting of several "subapps". Basically, the main application area is an ApplicationControlBar with buttons for each of the subapps. The rest of the area is a canvas where the subapps are displayed. Only one subapp is visible at a time. When switching between subapps, we do a canvas.removeAllChildren(), then canvas.addChild(subAppSwitchedTo). It's essentially a manual implementation of a ViewStack (the pros and cons of which are not the topic of this, so refrain from commenting on this).
Problem: In one of my subapps (let's say subapp "A"), I have a search function where results are displayed in a TitleWindow that gets popped up. Workflow is like enter search criteria, click search button, TitleWindow pops up with results (multiple selection datagrid), choose desired result(s), click OK, popup goes away (PopUpManager.removePopUp), and continue working. This all works fine. The problem is if I switch to a different subapp (say "B" -- where A gets removeAllChildren()'d and B gets added), then switch back to A and search again, when the results TitleWindow pops open, there will be TWO stacked on top of each other. If I continue to navigate away and back to A, every time I search, there will be an additional popup in the "stack" of popups (one for each time A gets addChild()'d).
Has anyone else experienced this? I'm not sure what to do about it and it's causing a serious usability bug in my application. Does this ring any bells to anyone? It's like I somehow need to flush the PopUpManager or something (even though I'm correctly calling removePopUp() to remove the TitleWindow). Please help!
EDIT
Flex SDK = 4.5.1
// Subapp "A"
if (!certificateSearchTitleWindow)
{
certificateSearchTitleWindow = new CertificateSearchTitleWindow;
certificateSearchTitleWindow.addEventListener("searchAccept", searchOKPopupHandler);
certificateSearchTitleWindow.addEventListener("searchCancel", searchClosePopupHandler);
}
PopUpManager.addPopUp(certificateSearchTitleWindow, this, true);
My guess is that the popup is removed from the main display list when you remove its parent (this in the PopUpManager.addPopup() method), but not from its parent display list. Why don't you listen, in your subapps, to the Event.REMOVED event, and then remove your popup ? That would be :
private var pp:CertificateSearchTitleWindow;
private function onCreationComplete():void
{
addEventListener(Event.REMOVED, onRemovede);
}
private function addPopUp():void
{
if (!pp) {
pp = new CertificateSearchTitleWindow();
PopUpManager.addPopUp(pp, this, true);
}
}
private function onRemoved(event:Event):void
{
if (pp) {
PopupManager.removePopUp(pp);
pp = null;
}
}
Thank you to those who gave suggestions. It turned out I was re-registering an eventListener over and over.
I am using a singleton to act as "shared memory" between the subapps. I was setting singleton.addEventListener(someType, listener) in subapp A's creationComplete callback. So everytime I navigated back to A, the creationComplete was running and re-adding this listener. After the search, the listener method (that opened the popup) was being called multiple times, i.e., as many times as the event had been added.
xref: http://forums.adobe.com/message/3941163
Sometimes when opening a form or when clicking on an object on the form, the form goes inactive or opens in the background. Is there a way to prevent this from occurring programatically?
I have seen this from time to time, but I don't have any documented solution.
You could try to clear the users AUC cache and see if that helps.
I have found the answer to this question. It is related to a 3rd party addition that we have installed (IEM). I had to remove some code that they have that sets forms as modal (which ends up putting them in the background because of the base timeout function in AX because the code to make the form modal takes too long to execute). I had to make a change to Classes/SysSetupFormRun: Below is the code and where it was changed
public void activate(boolean _active)
{
;
// if (_active)
// PUL_Modal::construct().hookModal(this);
super(_active);
/*
if (_active)
PUL_Modal::construct().checkModal(this);
*/
}
This returns the activate method to its previous state and prevents forms from going modal.