Intereting Posts
Уведомление Android Push без использования GCM Java: масштабирование карты Mapsforge при использовании онлайн-растровых изображений вместо автономного рендеринга Ускорение системы координат устройства в абсолютную систему координат В чем разница между безголовым фрагментом и службой на Android? Привязка данных Android (аналогично WPF)? Воспроизведение кнопки «Готово» в EditText? Библиотека поддержки Android v7: ошибка получения родительского элемента Получить контекст в классе без активности Когда isGooglePlayServicesAvailable возвращает SERVICE_VERSION_UPDATE_REQUIRED? Как я обнаружу датчик движения в широковещательном приемнике? Запросы HTTP-сообщений с использованием HttpClient занимают 2 секунды, почему? Почему в любом репозитории Maven нет Android SDK Jars? PANIC: Разбитый путь системы AVD. Проверьте значение ANDROID_SDK_ROOT В приложении Android toolbar.setTitle не действует – имя приложения отображается как заголовок : Использование функций Java и сторонних библиотек в Qt для Android

Фрагменты не освобождаются из памяти

У меня есть активность, которая содержит View Pager с адаптером FragmentStatePagerAdapter. Каждый раз, когда вы входите в действие, он занимает 200 мб памяти, после выхода из работы (финиш ()), а затем повторного ввода, он добавит и удвоит память, используемую на телефоне.

После устранения неполадок кажется, что менеджер фрагментов не выпускает фрагменты, хотя я пытаюсь их удалить, но просто не работает.

Я попытался опорожнить фрагмент, который добавляется, чтобы убедиться, что он не является чем-то внутренним внутри фрагмента, проблема остается.

Мой код адаптера

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); } } 

Мой код активности

  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); } } 

Код фрагмента:

 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; } } 

Пожалуйста, посоветуйте … Спасибо

Solutions Collecting From Web of "Фрагменты не освобождаются из памяти"

Сам ViewPager имеет метод setOffscreenPageLimit который позволяет указать количество страниц, поддерживаемых адаптером. Таким образом, ваши фрагменты, которые находятся далеко, будут уничтожены.

Прежде всего, глядя на ваш код, я не вижу, чтобы вы делали какие-либо действия по освобождению памяти в своих фрагментах onDestroy (). Тот факт, что сам фрагмент уничтожен и gc'ed не означает, что все выделенные вами ресурсы были удалены.

Например, моя большая проблема:

 imageLoader = ImageLoader.getInstance(); imageLoader.displayImage(childBean.childphoto, childimg, options); 

Из того, что я вижу здесь, кажется, что есть статический экземпляр ImageLoader, который вызывается каждый раз, когда появляется новый фрагмент, но я не вижу, где умирающий фрагмент попросит ImageLoader разгрузить его. Это выглядит подозрительно для меня.

Если бы я был вами, я бы сбросил файл HPROF моего приложения в тот момент, когда потребовалось дополнительно 200 мб (как вы утверждаете) после перезапуска активности и анализа ссылок через MAT (инструмент анализатора памяти). У вас явно есть проблемы с утечкой памяти, и я очень сомневаюсь, что проблема заключается в том, что сами фрагменты не уничтожаются.

Если вы не знаете, как анализировать кучу памяти, вот хорошее видео . Я не могу подсчитать, сколько раз это помогало мне идентифицировать и избавляться от утечек памяти в моих приложениях.

Не храните «сильные» ссылки на ViewPager или ImageView в своем фрагменте. Вы создаете циклическую ссылку, которая будет хранить все в памяти. Вместо этого, если вы должны сохранить ссылку на ViewPager или любой другой элемент, который ссылается на его контекст вне вашей активности, попробуйте использовать WeakReference, например:

 private WeakReference<ViewPager> mPagerRef; ... mPagerRef = new WeakReference<ViewPager>(mPager); ... final ViewPager pager = mPagerRef.get(); if (pager != null) { pager.setCurrentItem(...); } 

Следуя этому шаблону с помощью объектов, которые хранят ссылку на контекст Activity или Application (подсказка: любая ViewGroup, ImageView, Activity и т. Д.), Следует предотвращать появление «утечек памяти» в форме «циклов сохранения».

Кажется, что ваш код не разрушает представление, проверьте, что этот элемент Destroy из адаптера ViewPager может решить эту проблему.

После использования инструмента анализатора памяти в eclipse я узнал, что то, что прилипает в моей памяти, является фактическим расположением моих фрагментов. Относительная компоновка в определенном.

Причиной этого является CustomTextView, который я создал, который имеет собственный шрифт, заданный как шрифт.

  Typeface face=Typeface.createFromAsset(context.getAssets(), "Helvetica_Neue.ttf"); this.setTypeface(face); 

Чтобы решить проблему утечки памяти, я просто нашел здесь следующий ответ:

 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; } }