Tengo un fragmento (F1) con un método público como este
public void asd() {
if (getActivity() == null) {
Log.d("yes","it is null");
}
}
y sí, cuando lo llamo (de la Actividad), es nulo ...
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();
Debe ser algo que estoy haciendo muy mal, pero no sé qué es eso
getActivity()
. Además, ¿cómo estás instanciando el fragmento? ¿Lo tienes en tu layout.xml?Respuestas:
commit
programa la transacción, es decir, no sucede de inmediato, pero está programada como trabajo en el hilo principal la próxima vez que el hilo principal esté listo.Sugeriría agregar un
método
Fragment
y poner un punto de interrupción y ver cuándo se llama en relación con su llamada aasd()
. Verá que se llama después del método donde realiza la llamada a lasasd()
salidas. LaonAttach
llamada es dondeFragment
se adjunta a su actividad y desde este puntogetActivity()
devolverá no nulo (nb también hay unaonDetach()
llamada).fuente
onCreateView
oonActivityCreated
métodos. Me pregunto por qué se debe llamar a asd () cuando lo hace en la publicación de preguntas.commitNow()
Lo mejor para deshacerse de esto es mantener la referencia de actividad cuando se llama a onAttach y usar la referencia de actividad donde sea necesario, por ejemplo
fuente
onDestroy()
yonDetach()
porqueonDestroy()
no se garantiza que se llame.Activity
si no lo anulamosonDestroy()
?Esto sucedió cuando llamas
getActivity()
a otro hilo que terminó después de que el fragmento ha sido eliminado. El caso típico es llamargetActivity()
(por ejemplo, aToast
) cuando finaliza una solicitud HTTP (onResponse
por ejemplo, en).Para evitar esto, puede definir un nombre de campo
mActivity
y usarlo en lugar degetActivity()
. Este campo se puede inicializar en el método onAttach () de Fragment de la siguiente manera:En mis proyectos, generalmente defino una clase base para todos mis Fragmentos con esta característica:
Feliz codificación,
fuente
Activity
desde otro hilo en absoluto. De todos modos, no puedes hacer nada con él, ni siquiera mostrar un brindis. Por lo tanto, primero debe transferir el trabajo al hilo principal o no usar Actividad en absoluto.Las otras respuestas que sugieren mantener una referencia a la actividad en onAttach solo sugieren una venda al problema real. Cuando getActivity devuelve nulo, significa que el Fragmento no está adjunto a la Actividad. Lo más común es que esto ocurra cuando la Actividad se ha ido debido a la rotación o al final de la Actividad, pero el Fragmento todavía tiene algún tipo de escucha de devolución de llamada registrada. Cuando se llama al oyente si necesita hacer algo con la Actividad pero la Actividad se ha ido, no hay mucho que pueda hacer. En su código solo debe verificar
getActivity() != null
y si no está allí, no hagas nada. Si mantiene una referencia a la Actividad que se ha ido, está evitando que la Actividad se recolecte basura. El usuario no verá las cosas de la interfaz de usuario que intente hacer. Me imagino algunas situaciones en las que en el oyente de devolución de llamada es posible que desee tener un contexto para algo no relacionado con la interfaz de usuario, en esos casos, probablemente tenga más sentido obtener el contexto de la aplicación. Tenga en cuenta que la única razón por la que elonAttach
truco no es una gran pérdida de memoria es porque, normalmente, después de que se ejecuta la escucha de devolución de llamada, ya no será necesaria y se puede recolectar basura junto con el Fragmento, todas sus Vistas y el contexto de Actividad. Si tusetRetainInstance(true)
existe una mayor posibilidad de una pérdida de memoria porque el campo Actividad también se retendrá, pero después de la rotación podría ser la Actividad anterior y no la actual.fuente
Desde el nivel 23 de la API de Android, onAttach (Actividad de actividad) ha quedado en desuso. Debe usar onAttach (contexto de contexto). http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)
La actividad es un contexto, por lo que si simplemente puede verificar el contexto, es una actividad y emitirla si es necesario.
fuente
PJL tiene razón. He usado su sugerencia y esto es lo que he hecho:
Variables globales definidas para el fragmento:
private final Object attachingActivityLock = new Object();
private boolean syncVariable = false;
implementado
3) Terminé mi función, donde necesito llamar a getActivity (), en thread, porque si se ejecutara en thread principal, bloquearía el thread con el paso 4. y onAttach () nunca sería llamado.
4) en mi función donde necesito llamar a getActivity (), uso esto (antes de la llamada getActivity ())
Si tiene algunas actualizaciones de la interfaz de usuario, recuerde ejecutarlas en el hilo de la interfaz de usuario. Necesito actualizar ImgeView, así que hice:
fuente
El orden en que se llaman las devoluciones de llamada después de commit ():
Necesitaba hacer un trabajo que involucrara algunas vistas, por lo que onAttach () no funcionó para mí; se estrelló. Así que moví parte de mi código que estaba configurando algunos parámetros dentro de un método llamado justo después de commit () (1.), luego la otra parte del código que manejaba la vista dentro de onCreateView () (3.).
fuente
Estoy usando OkHttp y acabo de enfrentar este problema.
Para la primera parte, @thucnguyen estaba en el camino correcto .
Algunas llamadas HTTP se estaban ejecutando incluso después de que se cerró la actividad (porque puede llevar un tiempo completar una solicitud HTTP). Luego, a través del
HttpCallback
intento de actualizar algunos campos Fragmento y obtuve unanull
excepción al intentarlogetActivity()
.En mi opinión, la solución es evitar que se produzcan devoluciones de llamada cuando el fragmento ya no está vivo (y eso no es solo con Okhttp).
La solución: prevención.
Si usted tiene una mirada en el ciclo de vida del fragmento (más información aquí ), usted notará que hay
onAttach(Context context)
yonDetach()
métodos. Estos se llaman después de que el Fragmento pertenece a una actividad y justo antes de dejar de serlo, respectivamente.Eso significa que podemos evitar que esa devolución de llamada suceda al controlarla en el
onDetach
método.fuente
¿Dónde llamas a esta función? Si lo llama en el constructor de
Fragment
, volveránull
.Simplemente llame
getActivity()
cuandoonCreateView()
se ejecute el método .fuente
Haz lo siguiente. Creo que te será útil.
fuente
Aquellos que todavía tienen el problema con onAttach (Actividad de actividad), simplemente cambió a Contexto:
En la mayoría de los casos, guardar el contexto será suficiente para usted; por ejemplo, si desea obtener getResources (), puede hacerlo directamente desde el contexto. Si aún necesita incluir el contexto en su Actividad, hágalo:
Según lo sugerido por el usuario1868713.
fuente
Puede usar onAttach o si no desea poner onAttach en todas partes, puede poner un método que devuelva ApplicationContext en la clase principal de la aplicación:
Después de eso, puede reutilizarlo en todas partes en todo su proyecto, de esta manera:
Por favor, avíseme si esto no funciona para usted.
fuente
Otra buena solución sería usar LiveData de Android con la arquitectura MVVM. Definiría un objeto LiveData dentro de su ViewModel y lo observaría en su fragmento, y cuando se cambie el valor de LiveData, notificará a su observador (fragmento en este caso) solo si su fragmento está en estado activo, por lo que se garantizará que haría que su IU funcione y acceda a la actividad solo cuando su fragmento esté en estado activo. Esta es una ventaja que viene con LiveData
Por supuesto, cuando se hizo esta pregunta por primera vez, no había LiveData. Dejo esta respuesta aquí porque, como veo, todavía existe este problema y podría ser útil para alguien.
fuente
Llame al método getActivity () dentro de onActivityCreated ()
fuente