Esta clase de controlador debe ser estática o pueden producirse fugas: AsyncQueryHandler
Fugas de referencia del manejador Dado que este Handler se declara como una clase interna, puede impedir que la clase externa sea recolectada. Si el controlador utiliza un Looper o MessageQueue para un subproceso distinto del subproceso principal, no hay ningún problema. Si el controlador utiliza el Looper o MessageQueue del subproceso principal, debe corregir su declaración de controlador, de la siguiente manera: Declare el controlador como una clase estática; En la clase externa, instanciar una WeakReference a la clase externa y pasar este objeto a su Handler cuando instancie el Handler; Haga todas las referencias a miembros de la clase externa utilizando el objeto WeakReference.
¡Necesito una solución !!!!!
- Consulta getContentResolver causa la advertencia CursorWrapperInner
- Caída del evento debido a la ventana sin foco
- Recursos de Android ¿Por qué java piensa que la cadena es un número entero?
- Extrañas excepciones en android 4.0 con eclipse
- ¿Está bien tener tantos métodos obsoletos en el código compatible con versiones anteriores?
public class EMG_Activity extends AppCompatActivity { // An object that manages Messages in a Thread public static Handler HandlerMessager; private static AsyncQueryHandler queryHandler; private static final String EMG = "EMG"; private ManageConnectedSocket manageConnectedSocket; private Thread manageThread; private Button button_start_pause; private int id = 0; private int xValue = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_emg); queryHandler = new AsyncQueryHandler(getContentResolver()) { @Override protected void onInsertComplete(int token, Object cookie, Uri uri) { if(cookie != null) id = (int) ContentUris.parseId(uri); } }; ........... button_start_pause = (Button) findViewById(R.id.button_start_pause); button_start_pause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { .................. manageConnectedSocket = new ManageConnectedSocket(MainActivity.bluetoothDevice, MainActivity.samplingFrequency, new int[]{0}, new int[]{1, 0, 1, 1}); manageThread = new Thread(manageConnectedSocket); manageThread.start(); ContentValues values = getContentValuesExam (EMG, AlsrmSchema.PROGRESS, Utils.getCurrentDate()); queryHandler.startInsert(1, id, AlsrmContract.Exam.CONTENT_URI, values); ...... } }); } @Override public void onDestroy() { super.onDestroy(); ..... ContentValues values = getContentValuesExam (EMG, AlsrmSchema.CORRUPTED, Utils.getCurrentDate()); queryHandler.startUpdate(1, null, AlsrmContract.Exam.CONTENT_URI, values, AlsrmSchema.id + " = ? ", new String[]{"" + id}); } } }
- El proyecto hace referencia a los atributos de RTL, pero no activa o desactiva explícitamente el soporte RTL
- "No hay teclado para id 0" - ¿qué significa?
- KitKat ART-construcción de advertencia
- ¿Qué significa el triángulo naranja en la columna de destino de la ventana de Selección de dispositivo Android?
- Advertencia de Android Studio: Utilizar complementos incompatibles para el procesamiento de anotaciones
- Advertencia de InputConnectionWrapper
- Cómo reactivar una advertencia de Android Lint deshabilitada en el nivel de archivo
- Cómo desactivar las advertencias de @string resource en eclipse para el SDK de Android
Considere el siguiente código:
public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message msg) { // ... } } }
Aunque no es obvio, este código puede causar una pérdida masiva de memoria. Android Lint dará la siguiente advertencia:
In Android, Handler classes should be static or leaks might occur.
Pero, ¿dónde está exactamente la fuga y cómo podría suceder? Determinemos la fuente del problema documentando primero lo que sabemos:
- Cuando se inicia una aplicación de Android, el framework crea un objeto Looper para el subproceso principal de la aplicación. Un Looper implementa una cola de mensajes simple, procesando objetos de mensaje en un bucle uno tras otro. Todos los principales eventos del marco de aplicación (como las llamadas al método del ciclo de vida de la actividad, los clics de botón, etc.) están contenidos dentro de los objetos de mensaje, que se agregan a la cola de mensajes del Looper y se procesan uno a uno. El Looper del hilo principal existe en todo el ciclo de vida de la aplicación.
- Cuando un Handler se instancia en el subproceso principal, se asocia con la cola de mensajes del Looper. Los mensajes enviados a la cola de mensajes contendrán una referencia al Handler para que el framework pueda llamar a Handler # handleMessage (Message) cuando el Looper eventualmente procese el mensaje.
- En Java, las clases no-estáticas internas y anónimas contienen una referencia implícita a su clase externa. Las clases internas estáticas, por el contrario, no.
Entonces, ¿dónde está exactamente la pérdida de memoria? Es muy sutil, pero considere el código siguiente como un ejemplo:
public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message msg) { // ... } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Post a message and delay its execution for 10 minutes. mLeakyHandler.postDelayed(new Runnable() { @Override public void run() { /* ... */ } }, 1000 * 60 * 10); // Go back to the previous Activity. finish(); } }
Cuando se termina la actividad, el mensaje retrasado continuará viviendo en la cola de mensajes del subproceso principal durante 10 minutos antes de ser procesado. El mensaje contiene una referencia al controlador de la actividad y el controlador contiene una referencia implícita a su clase externa (la SampleActivity, en este caso). Esta referencia se mantendrá hasta que se procese el mensaje, evitando así que el contexto de actividad se recolecte de basura y se filtre todos los recursos de la aplicación. Tenga en cuenta que lo mismo ocurre con la clase Runnable anónima en la línea 15. Las instancias no estáticas de clases anónimas contienen una referencia implícita a su clase externa, por lo que el contexto se filtrará.
Para solucionar el problema, subclase el controlador en un archivo nuevo o utilice una clase interna estática en su lugar. Las clases internas estáticas no tienen una referencia implícita a su clase externa, por lo que la actividad no se filtrará. Si necesita invocar los métodos de la actividad externa desde dentro del Handler, haga que el manejador mantenga una WeakReference a la actividad para que no se filtre accidentalmente un contexto. Para corregir la pérdida de memoria que se produce cuando instanciamos la clase Runnable anónima, hacemos que la variable sea un campo estático de la clase (ya que las instancias estáticas de clases anónimas no contienen una referencia implícita a su clase externa):
public class SampleActivity extends Activity { /** * Instances of static inner classes do not hold an implicit * reference to their outer class. */ private static class MyHandler extends Handler { private final WeakReference<SampleActivity> mActivity; public MyHandler(SampleActivity activity) { mActivity = new WeakReference<SampleActivity>(activity); } @Override public void handleMessage(Message msg) { SampleActivity activity = mActivity.get(); if (activity != null) { // ... } } } private final MyHandler mHandler = new MyHandler(this); /** * Instances of anonymous classes do not hold an implicit * reference to their outer class when they are "static". */ private static final Runnable sRunnable = new Runnable() { @Override public void run() { /* ... */ } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Post a message and delay its execution for 10 minutes. mHandler.postDelayed(sRunnable, 1000 * 60 * 10); // Go back to the previous Activity. finish(); } }
La diferencia entre las clases internas estáticas y no estáticas es sutil, pero es algo que todos los desarrolladores de Android deben entender. ¿Cuál es la línea de fondo? Evite utilizar clases internas no estáticas en una actividad si las instancias de la clase interna podrían sobrevivir al ciclo de vida de la actividad. En su lugar, prefieren las clases internas estáticas y mantener una referencia débil a la actividad dentro.
- Nullpointerexception en getView de ArrayAdapter personalizado
- Android Async, Handler o temporizador?