I'm trying to get SlidingMenu to work alongside ViewPager and I have followed the examples inside the library to the letter. The source for my Activity can be found bellow.
The problem is that despite the fact that the SlidingMenu and ViewPager work fine together there is this problem that after opening the SlidingMenu for the first time and closing it afterwards the ViewPager starts acting weird.
By weird I mean when you swipe to right and left the UI gets stuck on one page and doesn't change and I mean it's only the UI as I can see in the logger that the pages actually change.
I have searched the web extensively and although there has been a lot of similar problems with implementing SlidingMenu alongside ViewPager, my problem seems to be unique.
Any help is appreciated.
public class MainTabActivity extends SlidingFragmentActivity {
private static final String TAG = "MainTabActivity";
#InjectView(R.id.tabHostPager)
ViewPager tabHostPager;
#InjectView(R.id.tabs)
PagerSlidingTabStrip tabStrip;
FragmentPagerAdapter pagerAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_tab);
setBehindContentView(R.layout.sliding_menu_layout);
loadSlidingMenu();
ButterKnife.inject(this);
pagerAdapter = new MainTabAdapter(getSupportFragmentManager());
tabHostPager.setAdapter(pagerAdapter);
//Assign the TabStrip it's ViewPager
tabStrip.setViewPager(tabHostPager);
tabStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
break;
default:
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
tabHostPager.setCurrentItem(0);
}
private void loadSlidingMenu() {
// configure the SlidingMenu
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
getSlidingMenu().setMode(SlidingMenu.LEFT);
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
getSlidingMenu().setShadowWidth(100);
getSlidingMenu().setFadeDegree(0.35f);
getSlidingMenu().setBehindWidth(width / 100 * 90);
}
private class MainTabAdapter extends FragmentPagerAdapter {
public MainTabAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 4;
}
#Override
public Fragment getItem(int position) {
return Friends.newInstance();
}
#Override
public CharSequence getPageTitle(int position) {
return "Home";
}
}
}
Finally I managed to solve it. It had something to with manageLayers method from the SlidingMenu class.
Commenting out the method body was all it took:
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void manageLayers(float percentOpen) {
/*if (Build.VERSION.SDK_INT < 11) return;
boolean layer = percentOpen > 0.0f && percentOpen < 1.0f;
final int layerType = layer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
if (layerType != getContent().getLayerType()) {
getHandler().post(new Runnable() {
public void run() {
Log.v(TAG, "changing layerType. hardware? " + (layerType == View.LAYER_TYPE_HARDWARE));
getContent().setLayerType(layerType, null);
getMenu().setLayerType(layerType, null);
if (getSecondaryMenu() != null) {
getSecondaryMenu().setLayerType(layerType, null);
}
}
});
}*/
}
Related
I using Fragment set cameraView
There is an error this onResume
#Override
public void onResume() {
super.onResume();
if (isCameraAccessGranted() && isRecordAudioGranted() && isWriteStorageGranted()) {
cvCamera.start();
} else {
ActivityCompat.requestPermissions(getActivity(), VIDEO_PERMISSIONS, 0);
}
}
I doing Stepper 5 Page Fragment this is PagerAdapter
public class PagerAdapter extends FragmentStatePagerAdapter {
public PagerAdapter(FragmentManager supportFragmentManager, int behavior) {
super(supportFragmentManager, behavior);
}
#Override
public int getCount() {
return 6;
}
#Override
public Fragment getItem(int position) {
return new BlankFragmentTestCamera();
}
#Override
public CharSequence getPageTitle(int position) {
return "Page " + position;
}
}
Please help me.
ViewPager by default keeps previous and next fragment in the resumed state. So it's like one camera opened on three screens at the same time.
Please, try to
Use only 1 fragment with camera view
Use flag FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT for the ViewPager
I've prepared a small working demo, please, take a look
https://github.com/3akat/Ziggeo_CameraView_PagerDemo
my problem is pretty simple but I don't see how to solve it... I didn't find any response to this problem.
I have 2 viewPager and when a page is selected I want to know which viewPager it comes from in onPageSelected().
There is my code :
public class MainActivity {
private ViewPager mCardsPager;
private ViewPager mIpsPager;
private MyCreditCardsPagerAdapter mCardsAdapter;
private MyInstantPaiementPagerAdapter mIpsAdapter;
private List<PayMethod> mCards;
private List<PayMethod> mIps;
//fill Pager/Adapter/List
#Override
public void onPageSelected(int position) {
if () {//If the page comes from mCardsPager
//do Something with mCards
} else { //else the page comes from mIpsPager
//do Something with mIps
}
}
}
You can set different listeners for each ViewPager rather than implement on Activity class.
Like this
mCardsPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
AND
mIpsPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
Setting same OnPageChangeListener for multiple ViewPager will not work. You need to create a class which implements OnPageChangeListener. In this class add a constructor which takes ViewPager as an input parameter and hold the value in a data member. Finally, use this class for adding OnPageChangeListener
As many applications I have MainActivity with ViewPager.
When I select option in NavigationDrawer I want to change one fragment in ViewPager. So to achieve that I created something like this:
Option click listener:
#Override
public void onItemClick(View view, int pos) {
mainActivity.changeFragment(pos);
}
MainActivity method:
public void changeFragment(final int key) {
mDrawerLayout.closeDrawers();
new Handler(Looper.getMainLooper()).post(new Runnable(){
#Override
public void run() {
mainPagerAdapter.setKey(key);
}
});
}
And MainPagerAdapter:
public class MainPagerAdapter extends FragmentStatePagerAdapter {
public final static int NUM_OF_PAGES = 2;
private int mCurrentFragmentKey = 0;
public MainPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == HOME) {
if (mCurrentFragmentKey == 0)
return new Fragment1();
else
return new Fragment2();
} else
return new SecondViewPagerFragment();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return NUM_OF_PAGES;
}
public void setKey(int key) {
mCurrentFragmentKey = key;
notifyDataSetChanged();
}
Question:
Unfortunately it's not working properly because when I select option whole view stutters giving bad performance. How can I fix that?
Edit
I changed notifying pager that data set changed into this:
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
mainPagerAdapter.setKey(key);
}
}, 500);
And now everything works fine, but I'm not sure that is best solution. Could someone help me with this?
What about if you have various adapter that extends FragmentStatePagerAdapter and when you need to change the contents in the viewpager, you simple call pager.setAdapter(anotherAdapter)?
If setAdapter supply the views to be shown, changing the adapter probably will make the content of your viewpager change.
I'm running into memory issues with fragments and I could use some help as to the appropriate path to take. I cannot use a simple backstack because the application needs to retain several paths that the user takes within the application (and the user can jump back and forth). The navigation handles fragments in this way:
transaction.hide(currentFragment).show(newFragment).commit();
What I think would help my situation is having the view of the fragment temporarily destroyed and then recreated when the fragment gets placed back in view (instead of simply hiding the UI from the user's view). From reading the API, it doesn't sound like the hide method does this. Does anyone know if there are some built-in methods to the FragmentTransaction/FragmentManager/Fragment class that will allow me to do this?
Another option I'm considering is creating my own lifecycle for each fragment. I've explored using tabhost as well, but it doesn't appear it's going to solve the memory issues. If you have another idea, I'm open to it.
Thanks guys, I appreciate your help with this.
I came up with a solution to achieve a better memory managed solution (adapter-based) for having multiple user journeys saved at the same time (independent tabs with something that represents backstacks). I scrapped using the FragmentManager as it was not conducive to this behavior. I will leave my answer here in case anyone else runs into a similar problem of needing this idea of multiple backstacks using ViewPagers with FragmentStatePagerAdapter - one viewpager for each tab in their app (this can still be cleaned up more but you can get the jist):
Primary Activity:
public class MultiTabbedActivity extends FragmentActivity implements NavigationFragment.OnNavigationSelectedListener
{
private Page1Fragment mPage1;
private Page2Fragment mPage2;
private CustomFragment mCurrent;
private String mNav;
private List<CustomFragment> mPage1BackStack;
private List<CustomFragment> mPage2BackStack;
private CustomViewPager mPagerPage1;
private CustomViewPager mPagerPage2;
private boolean mUpdating = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// initialize the backstacks
mPage1BackStack = new ArrayList<CustomFragment>();
mPage2BackStack = new ArrayList<CustomFragment>();
mPage1 = new Page1Fragment();
mPage2 = new Page2Fragment();
mPage1BackStack.add(mPage1);
mPage2BackStack.add(mPage2);
mPagerPage1 = (CustomViewPager) findViewById(R.id.page1_fragment);
mPagerPage2 = (CustomViewPager) findViewById(R.id.page2_fragment);
mPagerPage1.setOffscreenPageLimit(3); //Customizable to determine how many
mPagerPage2.setOffscreenPageLimit(3); //fragments you want to hold in memory
mPagerPage1.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage1BackStack));
mPagerPage2.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage2BackStack));
displayPager(mPagerPage1);
mCurrent = mPage1;
mNav = GlobalConstants.PAGE_PAGE1;
}
private void displayPager(ViewPager pager)
{
mPagerPage1.setVisibility(ViewPager.GONE);
mPagerPage2.setVisibility(ViewPager.GONE);
pager.setCurrentItem(pager.getAdapter().getCount() - 1);
pager.getAdapter().notifyDataSetChanged();
pager.setVisibility(ViewPager.VISIBLE);
}
#Override
public void onNavSelected(String page)
{
if (page != null && page != "" && !mUpdating)
{
// Determine the Fragment selected
if (page.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
{
mNav = GlobalConstants.PAGE_PAGE1;
displayPager(mPagerPage1);
mCurrent = mPage1BackStack.get(mPage1BackStack.size() - 1);
}
else if (page.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
{
mNav = GlobalConstants.PAGE_PAGE2;
displayPager(mPagerPage2);
mCurrent = mPage2BackStack.get(mPage2BackStack.size() - 1);
}
}
}
#Override
public void onBackPressed()
{
PageFragment navFrag = null;
// Update the Navigation Menu to indicate the currently visible
// Fragment
try
{
mUpdating = true;
if (mPage1BackStack.size() > 1 && mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
{
mPagerPage1.setCurrentItem(mPage1BackStack.size() - 2);
mPage1BackStack.remove(mPage1BackStack.size() - 1);
navFrag = mPage1BackStack.get(mPage1BackStack.size() - 1);
mPagerPage1.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage1BackStack));
}
else if (mPage2BackStack.size() > 1 && mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
{
mPagerPage2.setCurrentItem(mPage2BackStack.size() - 2);
mPage2BackStack.remove(mPage2BackStack.size() - 1);
navFrag = mPage2BackStack.get(mPage2BackStack.size() - 1);
mPagerPage2.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage2BackStack));
}
else
{
super.onBackPressed();
}
if (navFrag != null)
mCurrent = navFrag;
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
mUpdating = false;
}
}
public void updateFragment(PageFragment newFragment)
{
if (mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
{
mPage1BackStack.add(newFragment);
displayPager(mPagerPage1);
}
else if (mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
{
mPage2BackStack.add(newFragment);
displayPager(mPagerPage2);
}
mCurrent = newFragment;
}
}
CustomViewPager:
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
CustomAdapter:
public class CustomFragmentAdapter extends FragmentStatePagerAdapter
{
List<CustomFragment> mFragments;
public CustomFragmentAdapter(FragmentManager fm, List<CustomFragment> fragments)
{
super(fm);
mFragments = fragments;
}
public List<PageFragment> getmFragments()
{
return mFragments;
}
public void setmFragments(List<CustomFragment> mFragments)
{
this.mFragments = mFragments;
}
#Override
public int getCount()
{
return mFragments.size();
}
#Override
public Fragment getItem(int position)
{
return (Fragment) (mFragments.get(position));
}
}
UI (wrapped inside a linear layout):
<fragment
android:id="#+id/navigation_fragment"
android:name="your.package.here.NavigationFragment"
android:layout_width="70dp"
android:layout_height="match_parent" />
<FrameLayout
android:id="#+id/page_fragment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="2" >
<your.package.here.CustomViewPager
android:id="#+id/page1_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<your.package.here.CustomViewPager
android:id="#+id/page2_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout>
I have an activity that contains a View Pager that has an adapter FragmentStatePagerAdapter.
each time enter the activity it will take up 200mb of memory, after going back out of the activity(finish()) and then re entering it it will append and double the memory used on the phone.
After troubleshooting the problem it seems as if the fragment manager is not releasing the fragments although im trying to remove them but its just not working.
I tried emptying the fragment that is being added to make sure its not something internal inside the fragment the the problem remains.
my adapter code is
private class ChildrenPagerAdapter extends FragmentStatePagerAdapter
{
private List<ChildBean> childrenBean;
public ChildrenPagerAdapter(FragmentManager fm, List<ChildBean> bean)
{
super(fm);
this.childrenBean = bean;
}
#Override
public int getItemPosition(Object object)
{
return PagerAdapter.POSITION_NONE;
}
#Override
public Fragment getItem(int position)
{
ReportFragment reportFragment = new ReportFragment();
reportFragment.childBean = childrenBean.get(position);
reportFragment.position = position;
reportFragment.mPager = mPager;
if(position == 0)
{
reportFragment.mostLeft = true;
}
if(position == childrenNumber - 1)
{
reportFragment.mostRight = true;
}
return reportFragment;
}
#Override
public int getCount()
{
return childrenNumber;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object)
{
// TODO Auto-generated method stub
super.destroyItem(container, position, object);
}
}
my activity code is
public class ReportActivity extends CustomActivity
{
public ImageLoader imageLoader;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
private int childrenNumber;
private int currentChild;
#Override
protected void onDestroy()
{
mPager.removeAllViews();
mPager.removeAllViewsInLayout();
mPager.destroyDrawingCache();
mPagerAdapter = null;
mPager = null;
System.gc();
super.onDestroy();
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setCustomTitle(string.title_activity_reports);
this.currentChild = getIntent().getIntExtra("itemselected", -1);
getSupportFragmentManager().
}
#Override
protected void onResume()
{
super.onResume();
mPager = (ViewPager) findViewById(R.id.vpchildren);
mPager.setOffscreenPageLimit(6);
childrenNumber = MainActivity.bean.size();
mPagerAdapter = new ChildrenPagerAdapter(getSupportFragmentManager(), MainActivity.bean);
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(currentChild);
}
}
Fragment code :
public class ReportFragment extends Fragment
{
public ChildBean childBean;
public int position;
public ImageView img;
public ImageLoader imageLoader;
public DisplayImageOptions options;
private int pee = 0;
private int poop = 0;
private double sleep = 0.0;
public ViewPager mPager;
public boolean mostLeft = false;
public boolean mostRight = false;
public ReportFragment()
{
}
#Override
public void onDestroyView()
{
super.onDestroyView();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.report_fragment, container, false);
if(mostLeft)
{
rootView.findViewById(id.btnleft).setVisibility(View.GONE);
}
if(mostRight)
{
rootView.findViewById(id.btnright).setVisibility(View.GONE);
}
rootView.findViewById(id.btnleft).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
});
rootView.findViewById(id.btnright).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
}
});
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
Date dobchild = new Date();
((TextView) rootView.findViewById(id.tvday)).setText(sdf.format(dobchild));
ImageView childimg = (ImageView) rootView.findViewById(id.img_child);
((TextView) rootView.findViewById(id.tvchildname)).setText(childBean.childname);
((TextView) rootView.findViewById(id.tvclassname)).setText(((CustomApplication) getActivity().getApplication()).preferenceAccess.getCurrentClassName());
Date dob = null;
String age = "";
try
{
dob = sdf.parse(childBean.childdob);
age = GeneralUtils.getAge(dob.getTime(), getString(string.tv_day), getString(string.tv_month), getString(string.tv_year));
}
catch(ParseException e)
{
// TODO:
}
((CustomTextView) rootView.findViewById(id.tvchildage)).setText(age);
DisplayImageOptions options =
new DisplayImageOptions.Builder().showImageForEmptyUri(drawable.noimage).showImageOnFail(drawable.noimage).showStubImage(drawable.noimage).cacheInMemory()
.imageScaleType(ImageScaleType.NONE).build();
imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(childBean.childphoto, childimg, options);
final TextView tvpee = (TextView) rootView.findViewById(id.tvpeetime);
final TextView tvpoop = (TextView) rootView.findViewById(id.tvpootimes);
final TextView tvsleep = (TextView) rootView.findViewById(id.tvsleeptime);
rootView.findViewById(id.btnaddpee).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
pee = pee + 1;
if(pee > 9)
{
Toast.makeText(getActivity(), getString(string.tvareyousurepee), Toast.LENGTH_LONG).show();
}
tvpee.setText(String.format(getString(string.tvtimes), pee));
}
});
rootView.findViewById(id.btnminuspee).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
if(pee > 0)
{
pee = pee - 1;
tvpee.setText(String.format(getString(string.tvtimes), pee));
}
}
});
rootView.findViewById(id.btnpluspoo).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
poop = poop + 1;
if(poop > 9)
{
Toast.makeText(getActivity(), getString(string.tvareyousurepoop), Toast.LENGTH_LONG).show();
}
tvpoop.setText(String.format(getString(string.tvtimes), poop));
}
});
rootView.findViewById(id.btnminuspoo).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
if(poop > 0)
{
poop = poop - 1;
tvpoop.setText(String.format(getString(string.tvtimes), poop));
}
}
});
rootView.findViewById(id.btnaddsleep).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
sleep = sleep + 0.25;
tvsleep.setText(String.format(getString(string.tvhours), sleep));
}
});
rootView.findViewById(id.btnminussleep).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
if(sleep > 0)
{
sleep = sleep - 0.25;
tvsleep.setText(String.format(getString(string.tvhours), sleep));
}
}
});
rootView.findViewById(id.btnsave).setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(getActivity(), "Report Saved.", Toast.LENGTH_LONG).show();
getActivity().finish();
}
});
return rootView;
}
}
Please advise... Thanks
ViewPager itself has a method setOffscreenPageLimit which allows you to specify number of pages kept by the adapter. So your fragments that are far away will be destroyed.
First of all looking at your code I don't see you doing any memory releasing measures in your fragments onDestroy(). The fact that fragment itself is destroyed and gc'ed does not mean all resources you allocated were removed too.
For example, my big concern is:
imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(childBean.childphoto, childimg, options);
From what I see here it seems that there is a static instance of ImageLoader that gets poked every time a new fragment appears, but I can't see where a dying fragment would ask ImageLoader to unload its stuff. That looks suspicious to me.
If I were you I would dump an HPROF file of my application the moment it took extra 200mb (as you claim) after activity restart and analyze references via MAT (memory analyzer tool). You are clearly having memory leaks issue and I highly doubt the problem is in Fragments themselves not being destroyed.
In case you don't know how to analyze memory heap, here is a good video. I can't count how many times it helped me identifying and getting rid of memory leaks in my apps.
Don't store 'strong' references to ViewPager or ImageView in your Fragment. You're creating a cyclical reference that will keep everything in memory. Instead, if you must keep a reference to ViewPager or any other element that references its context outside of your Activity, try using a WeakReference, e.g:
private WeakReference<ViewPager> mPagerRef;
...
mPagerRef = new WeakReference<ViewPager>(mPager);
...
final ViewPager pager = mPagerRef.get();
if (pager != null) {
pager.setCurrentItem(...);
}
Following this pattern with Objects that store a reference to the Activity or Application context (hint: any ViewGroup, ImageView, Activity, etc.) should prevent "memory leaks" in the form of "retain cycles" from occurring.
it seems that your code is not destroying the view, check this Destroy item from the ViewPager's adapter might solve this issue.
After using the memory analyzer tool in eclipse i found out that what is sticking in my memory is the actual layout of my fragments.
Relative layout in specific.
The reason for this is a CustomTextView that i created that has a custom font set as a typeface.
Typeface face=Typeface.createFromAsset(context.getAssets(), "Helvetica_Neue.ttf");
this.setTypeface(face);
To solve the memory leak i simply did the following answer found here:
public class FontCache {
private static Hashtable<String, Typeface> fontCache = new Hashtable<String, Typeface>();
public static Typeface get(String name, Context context) {
Typeface tf = fontCache.get(name);
if(tf == null) {
try {
tf = Typeface.createFromAsset(context.getAssets(), name);
}
catch (Exception e) {
return null;
}
fontCache.put(name, tf);
}
return tf;
}
}