Navigation drawer item click updating child fragment again and again - android

In navigation drawer i have a child fragment with a list view. By clicking the drawer item first time, the list view is displayed but when closing and reopening the drawer by clicking on the same drawer item, the list view in child fragment is updated i.e. new list item is added in the list view of child fragment with the previous values of list view ..please help..i am stuck
int select=0;
select=position-2;
String sendto =list.get(position-2).getIMEI();
String sendtoname=list.get(position-2).getName();
System.out.println(deviceIMEI+"--"+sendto+sendtoname);
Fragment fragment = new ChatFrag();
Bundle args1 = new Bundle();
args1.putString(ChatFrag.MYIEMI, deviceIMEI);
args1.putString(ChatFrag.SENDERIEMI, sendto);
args1.putString(ChatFrag.SENDERNAME,sendtoname);
args1.putInt(ChatFrag.SELECT, select);
fragment.setArguments(args1);
fm.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
this is the code..please help how to remember the index..

Reason is that the Drawer ListView onItemClick will be called when ever an item in the List is clicked. This is the behavior of ListView.
One way to fix this is to keep remembering the last selected index and avoid adding the Fragment again on next time if the selected index is same as last selected.
Another way is to check the FragmentManager if the Fragment is already added
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
if(fragmentList != null) {
for (Fragment fragment : fragmentList) {
if (fragment != null && fragment instanceof CustomFragment) {
// don't add the fragment again
}else{
// add the fragment here
}
}

Related

Handeling events in nested fragments

Here is my problem, I am opening a new fragament from first fragment's Gridview item click. In my 1st fragment to refresh the items of grid view. I have implemented swipetoRefresh functionality.
But when I am opening the 2nd fragment to show my grid items in horizontal scrollview. Here also if I do swipe to refresh(swaping my finger from top to bottom). Then my first fragment event occurs. I dont want my first fragment event on 2nd fragment. Please let me know how can I resolve it.
Below is my code to open new Fragment.
Fragment newFragment = new SwipeFragment(featureArr, dataList, HomeFragment.this);
// Log.e("position clicked is","-----"+position);
Bundle b = new Bundle();
b.putInt("pos", position);
newFragment.setArguments(b);
FragmentTransaction transaction = ((AppCompatActivity)mContext).getSupportFragmentManager().beginTransaction();
transaction.add(R.id.frame_edit, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();

Fragment in ViewPager loses its view

I started a new project using tabbed activity of Android Studio. It created an activity with ViewPager and 3 fragments = fragment1, fragment2 and fragment3.
I changed fragment1 to have a listView and a TextView, that I initialize when the fragment is created. The data in the listView is read from an SQL database.
When the application starts, fragment1 is displayed and the listView shows the data read from SQL.
When I swipe from fragment1 to fragment2 and back, fragment1 shows the listview properly. However, when I swipe to fragment3 and back to fragment1 the listview data is lost and I get a blank screen, although the textview shows properly.
When I change the application to have only 2 fragments it does not happen and I can swipe from fragment1 to fragment2 and back many times without any loss of data. The moment I add the 3rd fragment, the data is lost on first swipe to fragment3, but is not lost if I swipe between fragment 1 and fragment2 only.
Any idea why is it happening?
This is happening because by default ViewPager has a function named setOffscreenPageLimit(int i). This tells ViewPager how many of the Fragments need to store in memory. By default it is '2'. So when you swipe to Fragment 2 from Fragment 1 it will still keep Fragment 1 in memory and won't destroy it from memory. But when you swipe to Fragment 3 it will have Fragment 2 and Fragment 3 in memory so it will remove Fragment 1.
That's why when you come back to your first Fragment it have lost its views or data.
Try to use
mViewPager.setOffscreenPageLimit(your total fragment count +1);
Or much better solution
Do not replace your fragment when you swipe in ViewPager. Push it to the backstack and when you comeback to it, Check for the backstack and if fragment is there then just Pop it and display it.
Here is the code:
public void pushFragments(String tag, Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (manager.findFragmentByTag(tag) == null) {
ft.add(R.id.frame_container, fragment, tag);
}
String tagOne="com........Frag_one"; //your fragment class name
String tagTwo="com........Frag_two";
String tagThree="com........Frag_three";
String tagFour="com........Frag_profile";
Fragment fragmentOne = manager.findFragmentByTag(tagOne);
Fragment fragmentTwo = manager.findFragmentByTag(tagTwo);
Fragment fragmentThree = manager.findFragmentByTag(tagThree);
Fragment fragmentFour = manager.findFragmentByTag(tagFour);
manager.executePendingTransactions();
// Hide all Fragment
if (fragmentOne != null) {
ft.hide(fragmentOne);
}
if (fragmentTwo != null) {
ft.hide(fragmentTwo);
}
if (fragmentThree != null) {
ft.hide(fragmentThree);
}
if (fragmentFour != null) {
ft.hide(fragmentFour);
}
// Show current Fragment
if (tag.equals(tagOne)) {
if (fragmentOne != null) {
ft.show(fragmentOne);
}
}
if (tag.equals(tagTwo)) {
if (fragmentTwo != null) {
ft.show(fragmentTwo);
}
}
if (tag.equals(tagThree)) {
if (fragmentThree != null) {
ft.show(fragmentThree);
}
}
if (tag.equals(tagFour)) {
if (fragmentFour != null) {
ft.show(fragmentFour);
}
}
ft.commit();
}
And Here is how you call it:
Fragment fragment = new Frag_one();
pushFragments(fragment.getClass().getName(),fragment);
Issue solved. The problem is due to the adapter keeping 3 fragments in memory, as pointed by #Daniel Nugent. The data in the pages is loaded from DB so that when the view is recreated, when fragments are destroyed and recreated as the user swipes, the listview adapter has lost the data, and one has to repopulate it. The problem does not appear on simple examples because usually the data presented is static and is loaded in the onCreateView method.

Transfer Data Between two hierarchical fragments inside activity?

I have A Navigation Drawer with list of items , and on click on a list item opens
another list of events(with A custom list adapter)[1 st fragment].
And a click on any of any of that list item i want to open a fragment which displays its details[2 st fragment] .
So i want to transfer position of item click from 1st frag to 2 nd frag ,
i have static data in 2 nd frag , how do i transfer that position ?
I tried with interface ,
but with every time i do anything i get error in logcat as 1st fragment is not attached to Main activity .
And i have created layout(and referred them as fragment) and there is NO so no Id to get in mainactivity in 'getFragmentById' ? Thanks .
Pass data in constructor of fragment
FragmentManager fm = SliderActivity.this
.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
HomeFragment fragment = new HomeFragment(your_data);
ft.replace(R.id.content_fragment, fragment, getResources()
.getString(R.string.homeText));
ft.commit();
in HomeFragment set the value from constructor
HomeFragment(String value){
this.value=value;
}
You can use getActivity() from a fragment to find the FragmentActivity in which the fragment resides.
Then you can use FragmentActivity.findFragmentByTag() to find the other fragment in this Actvity. `

Android ListView is reloading all of the items (rather than just appending the new item) after I return back from a fragment

Android ListView is reloading all of the items (rather than just appending the new item) after I return back from a fragment where i inserted a new item onto the listview (in another fragment, ListFragment)
I have the following code to launch a fragment through Navigation Drawer:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
SherlockFragment frag = null;
// Locate Position
switch (position) {
case 0:
frag = ListFragment.newInstance();
ft.replace(R.id.content_frame, frag);
break;
case 1:
frag = InsertNewsFragment.newInstance();
ft.replace(R.id.content_frame, frag);
break;
default:
frag = UnderConstructionFragment.newInstance();
ft.replace(R.id.content_frame, frag);
break;
}
ft.commit();
listview.setItemChecked(position, true);
drawlayout.closeDrawer(listview);
The issue is that when I initially load the activity ListFragment is launched, but when user opens the navigation drawer and selects the add News, I replace the current fragment with the InsertNewsFragment, the insertNewsFragment adds data to the adapter that is displayed in the ListFragment. After adding the news element, the user selects the list fragment option in the navigation drawer, but I would expect the same listview to be there and just append the new data to the listview. But what happens is that the whole listview is loaded from scratch again. Can show me the way to how item can be appended to the list view when I return from another fragment, and not reload the whole listview. Thanks in advance :)
you cannot do this as you are replacing the listfragment. Initially you will have to check if the listview is opened if it comes out to be true then close all the other fragments that are opened and bring it (The listview fragment) to the top then dont set the adapter again and again just use the notifydatasetchanged method

getFragmentByTag() never returns null

I've five fragments in my activity. On the click of fragment drawer list, I'm calling setFrament() method.
It removes the previous fragments from the activity, and adds the new one as per the requirement.
Here's my code for setFragment method.
protected void setFragment(final int position) {
// Remove currently active fragment
if (mActiveFragment != null) {
Fragment previous;
while ((previous = mFragmentManager
.findFragmentByTag(mActiveFragment.toString())) != null) {
mFragmentManager.beginTransaction().remove(previous).commit();
Log.e("in loop", "stuck");
}
}
// It's enum, generated according to position
FragmentType type = getFragmentType(position);
Fragment fragment = mFragmentManager.findFragmentByTag(type.toString());
if (fragment == null) {
fragment = createFragment(type);
}
mFragmentManager
.beginTransaction()
.replace(R.id.containerFrameLayout, fragment,
type.toString()).commit();
// Sets the current selected fragment checked in
// Drawer listview
mFragmentDrawerList.setItemChecked(position, true);
// set Actionbar title
getActionBar().setTitle(type + "");
mActiveFragment = type;
}
Here, while changing the fragment, it keeps prining "stuck" in while loop forever,
my question is,
why remove(Fragment) method doesn't remove the previous fragment from the activity ?
commit() is an asynchronous call that is only executed when the Android system regains control. The fragments won't be removed until some time after you leave the method.
If you want to remove the previous fragment (assuming there's only one), then you can add them to the backstack. Then you can call popBackStack(null, 0) which will pop everything on the back stack. The side catch though is pressing the "back" button will also pop the backstack if the user were to do that. You'll have to override the onBackPressed() and handle it yourself if you don't want that to happen.
EDIT:
One method would be to keep track of all IDs or TAGs and call remove on them individually.
LinkedList<Integer> fragmentIds = new LinkedList<Integer>();
/*** Add fragment to FragmentManager ***/
fragmentIds.add(/** ID of fragment */);
/** Removing all fragments from FragmentManager **/
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
Fragment fragToRemove;
for(Integer id : fragmentIds)
{
fragToRemove = fm.findFragmentById(id);
transaction.remove(fragToRemove);
}
transaction.commit()
fragmentIds.clear();
However, you don't have to call remove on any of them so long as you use replace() method on the same container. replace() will pop the previous fragment and add in the new one. So long as the transaction isn't pushed to the backstack, the previous fragment is detached from the Activity and discarded.

Categories

Resources