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 –
- Lazy carga en HorizontalScrollView para evitar el problema de memoria insuficiente
- Error de memoria en el emulador de Android, pero no en el dispositivo
- BitmapFactory OOM me conduce nueces
- Error de memoria de mapa de bits - Android
- Android pinch zoom imagen grande, memoria eficiente sin perder detalle
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(); }
- Cuando Android ofrece Excepción OutOfMemory?
- MapFragment Google Maps API v2 Fuera de error de memoria / pérdida de memoria
- El tamaño de mapa de bits supera el presupuesto de VM cuando el desarrollo de juegos
- Error de falta de memoria al analizar un JSON grande con la biblioteca de Jackson en Android
- Señal fatal 11 (SIGSEGV) en 0x00000000 (código = 1), hilo 27830 (ple.myfragexample) - sólo en Android 4.1.2
- Causa de OutOfMemoryError en la animación de marco por cuadro en Android
- OutOfMemoryException al cargar imágenes de gran tamaño usando glide
- Android Insertar palabras en ArrayList, sin memoria
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.
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(); }
- En un EditText, ¿hay una manera de desactivar la autocorrección en un span?
- Android: ¿Cómo mejorar los números dentro de la imagen recuperada por tesseract ocr?