Problemas de memoria en fragmentos que muestran imágenes

Estoy utilizando fragmentos para mostrar imágenes / páginas. Tengo una actividad (principal) que contiene todos los fragmentos.

package com.example.hscroll.demo; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.app.ListFragment; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.crittercism.app.Crittercism; import com.example.hscroll.customer.BitmapWeakReference; import com.example.hscroll.customer.PromotionalPriceListAdditionsDataAdaptor; import com.example.hscroll.customer.PromotionalPriceListDataAdaptor; import com.example.hscroll.library.imagezoom.ImageViewTouch; public class MainAct extends FragmentActivity{ private ImageViewTouch mImageView; MyPagerAdapter mPagerAdapter; ViewPager viewPager; static final int NUM_ITEMS = 58; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Crittercism.init(getApplicationContext(), "4f391d0fb09315319d00048d"); PreferenceManager.setDefaultValues(this, R.xml.preference, false); setContentView(R.layout.viewpager_layout); mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager()); viewPager = (ViewPager)findViewById(R.id.viewpager); viewPager.setAdapter(mPagerAdapter); } public static class MyPagerAdapter extends FragmentStatePagerAdapter { public MyPagerAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return NUM_ITEMS; } @Override public Fragment getItem(int position) { return newInstance(position); } } static Fragment newInstance(int position) { Fragment data = null; switch(position){ case 0 : data = new Fragment1(); break; case 1 : data = new FragmentSignupForm(); break; case 2 : data = new Fragment2(); break; case 3 : data = new Fragment3(); break; case 4 : data = new Fragment4(); break; case 5: data = new Fragment5(); break; case 6 : data = new Fragment6(); break; case 7 : data = new Fragment7(); break; case 8 : data = new Fragment8(); break; case 9 : data = new Fragment9(); break; case 10 : data = new MyMapFragment(); break; case 11: data = new FragmentQuestionaire(); break; case 12: data = new Fragment10(); break; case 13: data = new Fragment11(); break; case 14: data = new Fragment12(); break; case 15: data = new Fragment13(); break; case 16: data = new Fragment14(); break; case 17: data = new Fragment15(); break; case 18: data = new Fragment16(); break; case 19: data = new Fragment17(); break; case 20: data = new Fragment18(); break; case 21: data = new Fragment19(); break; case 22: data = new Fragment20(); break; case 23: data = new Fragment21(); break; case 24: data = new Fragment22(); break; case 25: data = new Fragment23(); break; case 26: data = new Fragment24(); break; case 27: data = new Fragment25(); break; case 28: data = new Fragment26(); break; case 29: data = new Fragment27(); break; case 30: data = new Fragment28(); break; case 31: data = new Fragment29(); break; case 32: data = new Fragment30(); break; case 33: data = new Fragment31(); break; case 34: data = new Fragment32(); break; case 35: data = new Fragment33(); break; case 36: data = new Fragment34(); break; case 37: data = new Fragment35(); break; case 38: data = new Fragment36(); break; case 39: data = new Fragment37(); break; case 40: data = new Fragment38(); break; case 41: data = new Fragment39(); break; case 42: data = new Fragment40(); break; case 43: data = new Fragment41(); break; case 44: data = new Fragment42(); break; case 45: data = new Fragment43(); break; case 46: data = new Fragment44(); break; case 47: data = new Fragment45(); break; case 48: data = new Fragment46(); break; case 49: data = new Fragment47(); break; case 50: data = new Fragment48(); break; case 51: data = new Fragment49(); break; case 52: data = new Fragment50(); break; case 53: data = new Fragment51(); break; case 54: data = new Fragment52(); break; case 55: data = new Fragment53(); break; case 56: data = new Fragment54(); break; case 57: data = new Fragment55(); break; default : data = new FragmentQuestionaire(); break; } return data; } @Override protected void onDestroy() { super.onDestroy(); FragmentSignupForm.CUSTOMER_ADDRESS = ""; FragmentSignupForm.CUSTOMER_ADDRESS1 = ""; FragmentSignupForm.CUSTOMER_ADDRESS2 = ""; FragmentSignupForm.CUSTOMER_EMAIL = ""; FragmentSignupForm.CUSTOMER_ID = ""; FragmentSignupForm.CUSTOMER_POSTCODE = ""; FragmentSignupForm.CUSTOMER_NAME = ""; FragmentSignupForm.Telephone = ""; Fragment50.Total = "0"; Fragment47.amount2 = 0; Fragment47.systemSize = ""; PromotionalPriceListAdditionsDataAdaptor.TotalAdditionalPrice = 0; PromotionalPriceListDataAdaptor.TotalPrice = 0; PromotionalPriceListDataAdaptor.Capacity = ""; PromotionalPriceListDataAdaptor.NumberOfPanels = ""; PromotionalPriceListDataAdaptor.PanelSize = ""; PromotionalPriceListDataAdaptor.PanelCapacity = ""; PromotionalPriceListDataAdaptor.SurfaceAreaReuired = ""; PromotionalPriceListDataAdaptor.Price = ""; PromotionalPriceListDataAdaptor.PromotionalOffer = ""; PromotionalPriceListDataAdaptor.TotalOfferPrice = ""; } } 

Aquí está el código en la clase de fragmento –

 package com.example.hscroll.demo; import java.io.BufferedInputStream; import java.io.FileInputStream; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.example.hscroll.customer.BitmapWeakReference; import com.example.hscroll.library.imagezoom.ImageViewTouch; public class Fragment2 extends Fragment{ ImageViewTouch imgview ; LayoutInflater inflater; FileInputStream in; BufferedInputStream buf; BitmapWeakReference bitmap; ViewGroup con; private final String PATH = "/mnt/sdcard/Ideal Solar/Layout_1.png"; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) { this.inflater = inflater; if(container == null)return null; container = (LinearLayout)inflater.inflate(R.layout.fragment0_layout, container, false); con = container; imgview= (ImageViewTouch)container.findViewById(R.id.imageView1); bitmap = new BitmapWeakReference(imgview.selectImage(inflater.getContext(), PATH)); if(bitmap!=null) imgview.setImageBitmapReset( bitmap.get(), true ); return container; } /* @Override public void onResume() { if(bitmap == null) { bitmap = SelectImageFunctions.selectImage(inflater.getContext(), PATH); } super.onResume(); }*/ @Override public void onDestroyView() { super.onDestroyView(); imgview.setImageBitmap(null); bitmap.clear(); bitmap = null; Fragment1.unbindDrawables(con.findViewById(R.id.ll)); System.gc(); } } 

Cada vez que me muevo al fragmento siguiente, el onDestroyView () del fragmento anterior se llama y estoy quitando todas las referencias de mapas de bits y visiones de imágenes, pero todavía la memoria de bitmaps o drawables no obtener liberado y la memoria sigue aumentando. Y finalmente se estrelló A unos 50 MB.

¿Puedo ayudar a alguien esto? Estoy desarrollando esta aplicación sólo para la pestaña de galaxias.

UPDATE – Código para página dinámica –

  package com.example.hscroll.demo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONObject; import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.Toast; public class FragmentSignupForm extends Fragment { LayoutInflater inflater; String result = null; InputStream is = null; StringBuilder sb = null; JSONArray jArray; EditText c_nameText; EditText c_addressText; EditText c_postcodeText; EditText c_emailText; EditText s_nameText; EditText c_addressLine2Text; EditText telephone_Text; public static String CUSTOMER_NAME = ""; public static String CUSTOMER_ADDRESS = ""; public static String CUSTOMER_ADDRESS1 = ""; public static String CUSTOMER_ADDRESS2 = ""; public static String CUSTOMER_POSTCODE = ""; public static String CUSTOMER_ID; public static String CUSTOMER_EMAIL = ""; public static String SALES_CONTACT = ""; public static String Telephone = ""; String output = null; ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); ViewGroup con; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) { this.inflater = inflater; if(container == null)return null; container = (ScrollView)inflater.inflate(R.layout.signup_form_layout, container, false); con = container; ScrollView sv = (ScrollView)container.findViewById(R.id.SV); sv.setBackgroundDrawable(AssestUtil.getBitmapFromAsset(inflater.getContext(), "bg.jpg")); LinearLayout ll = (LinearLayout)container.findViewById(R.id.ll); ll.setBackgroundDrawable(AssestUtil.getBitmapFromAsset(inflater.getContext(), "formbg2.png")); c_nameText = (EditText)container.findViewById(R.id.cust_name); c_nameText.setText(CUSTOMER_NAME); c_addressText = (EditText)container.findViewById(R.id.cust_address); c_addressText.setText(CUSTOMER_ADDRESS1); c_addressLine2Text = (EditText)container.findViewById(R.id.cust_Address2); c_addressLine2Text.setText(CUSTOMER_ADDRESS2); c_postcodeText = (EditText)container.findViewById(R.id.postcode); c_postcodeText.setText(CUSTOMER_POSTCODE); c_emailText = (EditText)container.findViewById(R.id.cust_email); c_emailText.setText(CUSTOMER_EMAIL); s_nameText = (EditText)container.findViewById(R.id.sales_name); s_nameText.setText(SALES_CONTACT); telephone_Text = (EditText)container.findViewById(R.id.telephone); telephone_Text.setText(Telephone); Button save = (Button)container.findViewById(R.id.save_btn); Button Reset = (Button)container.findViewById(R.id.reset_btn); final Context context = inflater.getContext(); //Send form data to server on click action save.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { CUSTOMER_NAME = c_nameText.getText().toString(); System.out.println(CUSTOMER_NAME); CUSTOMER_ADDRESS = c_addressText.getText().toString() + ","+ c_addressLine2Text.getText().toString()+","+c_postcodeText.getText().toString();; CUSTOMER_POSTCODE = c_postcodeText.getText().toString(); Telephone = telephone_Text.getText().toString(); new SendDataToServer().execute(c_nameText.getText().toString(),c_addressText.getText().toString(),c_addressLine2Text.getText().toString(),c_postcodeText.getText().toString(),c_emailText.getText().toString(),s_nameText.getText().toString(),telephone_Text.getText().toString()); InputMethodManager imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(s_nameText.getWindowToken(), 0); } }); Reset.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { c_nameText.setText(""); c_addressText.setText(""); c_addressLine2Text.setText(""); c_postcodeText.setText(""); c_emailText.setText(""); s_nameText.setText(""); telephone_Text.setText(""); } }); return container; } private class SendDataToServer extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { try { nameValuePairs.add(new BasicNameValuePair("cust_name",params[0])); nameValuePairs.add(new BasicNameValuePair("cust_address",params[1]+","+params[2])); nameValuePairs.add(new BasicNameValuePair("cust_postcode",params[3])); nameValuePairs.add(new BasicNameValuePair("cust_email",params[4])); nameValuePairs.add(new BasicNameValuePair("sales_name",params[5])); nameValuePairs.add(new BasicNameValuePair("pvgis_data", params[6])); HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://ideal.contrastgroup.info/idealsolar/initializeCustomer.php"); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); is = entity.getContent(); JSONObject myAway = new JSONObject(read(is)); CUSTOMER_ID = myAway.getString("custID"); output = myAway.getString("message"); } catch(Exception e) { output = "null"; } return output; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if(result.equalsIgnoreCase("success")) { Toast.makeText(inflater.getContext(), "Database updated", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(inflater.getContext(), "Error in Connection", Toast.LENGTH_SHORT).show(); } } } public static String read(InputStream in) throws IOException { StringBuilder sb = new StringBuilder(); BufferedReader r = new BufferedReader(new InputStreamReader(in)); for (String line = r.readLine(); line != null; line = r.readLine()) { sb.append(line); } in.close(); System.out.println(sb.toString()); return sb.toString(); } @Override public void onDestroyView() { super.onDestroyView(); Fragment1.unbindDrawables(con.findViewById(R.id.SV)); System.gc(); } 

}

  public static void unbindDrawables(View view) { if (view.getBackground() != null) { view.getBackground().setCallback(null); } if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { unbindDrawables(((ViewGroup) view).getChildAt(i)); } ((ViewGroup) view).removeAllViews(); } 

De Google:

Fragment State Pager Support Demuestra el uso de la clase de soporte ViewPager con un FragmentStatePagerAdapter para crear una interfaz de usuario en la que el usuario puede voltear a la izquierda oa la derecha para cambiar entre fragmentos. Esta versión del adaptador no guarda alrededor de las instancias de fragmentos que ViewPager ha destruido.

http://developer.android.com/resources/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStatePagerSupport.html

La diferencia con el paginador normal es que extiende FragmentStatePagerAdapter.

Editar: En el código de google tienes esto en el adaptador:

 public static class MyAdapter extends FragmentStatePagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return NUM_ITEMS; } @Override public Fragment getItem(int position) { return ArrayListFragment.newInstance(position); } } 

Observe la implementación de getItem (). Obtenemos un nuevo fragmento a petición, por lo que no crearemos el fragmento antes de que lo necesitamos. Esto está parado en contraste con su acercamiento donde usted crea todos los fragmentos y los agrega a un vector. (Java prefiere arraylists btw.) Con su acercamiento los fragmentos no serán quitados de memoria pues siempre habrá una referencia a los fragmentos.

Editar 2: Para ser específico. En lo siguiente:

 @Override public Fragment getItem(int position) { return ArrayListFragment.newInstance(position); } 

Usted podría hacer algo como:

  @Override public Fragment getItem(int position) { if(position == 1) { return Fragment1.newInstance(position); } else { return Fragment2.newInstance(position); } } 

Según documentaions OnDestroyView se llama cuando el fragmento ya no es visible como onStop para la actividad, pero en OnDestroy (Fragments) es equivalente a OnDestroy para Activity.

Así llamando unBindDrawable de OnDestroy de fragmentos debe liberar toda la memoria.

 @Override public void onDestroy() { super.onDestroy(); Utils.log(TAG, "onDestroy position ImageGridFragment"); unbindDrawables(mGridView); mGridView = null; gridAdapter = null; System.gc(); Runtime.getRuntime().gc(); } 

En primer lugar poner cheque nulo para todas las variables de mapa de bits, por ejemplo

 if(null==yourBitmapVar) //initialize yourBitmapVar here 

Por lo que todo el tiempo no se inicializa mapa de bits

Creo que este es el camino correcto .. y debería trabajar asumir que tiene dos fragmentos f1 y f2 que está utilizando dentro de actividad acto,

Y usted tiene 2 bitmap en f1

 bitmap a; bitmap b; 

Y de nuevo en 2 bitmaps en f2

 bitmap a; bitmap b; 

Ahora cada vez que inicializar estas var sólo utilizar el cheque nulo, si estos son nulos sólo entonces inicializarlos o bien no lo hacen .. entonces no se enfrentan a ningún problema de memoria,

Y si desea borrar su mapa de bits

 bitmap.clear(); 

Entonces cuando alguna vez cambias entre fragmentos debes inicializar bitmaps antes de mostrar nada … eso significa justo antes de supermodo. Y asegúrese de que cuando el fragmento llega a la visibilidad, el mapa de bits se inicializa

Creo que todo lo que necesitas hacer 🙂 codificación feliz

Gracias a la respuesta de todos-ok puedo arreglar mi error. Seguí saliendo de la memoria usando incluso onDestroy. He añadido este o el fragmento: Donde rl_todo es el RelativeLayout que contiene el gridview. Gv_productos es el filtro gridview es la actividad que contiene todas las vistas.

 @Override public void onDestroy() { super.onDestroy(); Log.i("onDestroy", "onDestroy position ImageGridFragment"); RelativeLayout rl_todo=(RelativeLayout) activity.findViewById(R.id.rl_todo); Utilidades.unbindDrawables(rl_todo); gv_productos = null; filtro = null; System.gc(); Runtime.getRuntime().gc(); } @Override public void onDestroyView() { super.onDestroyView(); Log.i("onDestroy", "onDestroy position ImageGridFragment"); RelativeLayout rl_todo=(RelativeLayout) activity.findViewById(R.id.rl_todo); Utilidades.unbindDrawables(rl_todo); gv_productos = null; filtro = null; System.gc(); Runtime.getRuntime().gc(); } 
  • Excepción OutOfMemory al cargar mapa de bits desde almacenamiento externo
  • Excepción "OutOfMemory" sólo en Samsung Galaxy S3
  • Fuera de error de memoria en android debido al aumento de tamaño de montón
  • SplashScreen con la imagen PNG conduce a Android.Views.InflateException seguido de OutOfMemory
  • Java.lang.OutOfMemoryError en almacenar imágenes en sqlite db
  • Android: Demasiada memoria asignada mientras usa png en lugar de imágenes vectoriales
  • Android: Error de OutOfMemory y el backstack
  • Error de falta de memoria de ImageView
  • Problemas con Google MapView OutOfMemoryError de Google
  • 75 marcadores en el mapa -> pérdidas de memoria -> OutOfMemoryException
  • Cómo evitar OutOfMemory ex mientras gira la imagen?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.