'Jobject' no debe ser IntPtr.Zero al ajustar el texto textview en MonoDroid

Estoy usando MvvmCross con MonoDroid.

En un temporizador en el viewmodel, cada minuto que llamo RaisePropertyChanged("MinutesRemaining")MinutesRemaining es un entero que especifica la duración en minutos hasta que termine la entrada actual (y sí, esto se llama en el subproceso de interfaz de usuario).

MinutesRemaining está enlazado a un TextView utilizando MvvmCross.

Hasta la actualización 4.10.1 de Xamarin, la aplicación se bloquearía completamente sin mensaje de error impreso en la traza. Ahora se está rompiendo correctamente al depurar y dar el siguiente error al invocar el evento PropertyChanged :

 MvxBind:Error:281.24 Problem seen during binding execution for binding Text for MinutesRemaining - problem ArgumentException: 'jobject' must not be IntPtr.Zero. Parameter name: jobject at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue[] parms) [0x00010] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/9d03ce3e/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:499 at Android.Widget.TextView.set_TextFormatted (ICharSequence value) [0x00034] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/9d03ce3e/source/monodroid/src/Mono.Android/platforms/android-14/src/generated/Android.Widget.TextView.cs:1814 at Android.Widget.TextView.set_Text (System.String value) [0x00013] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/9d03ce3e/source/monodroid/src/Mono.Android/platforms/android-14/src/generated/Android.Widget.TextView.cs:1823 at Cirrious.MvvmCross.Binding.Droid.Target.MvxTextViewTextTargetBinding.SetValueImpl (System.Object target, System.Object toSet) [0x00000] in <filename unknown>:0 at Cirrious.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue (System.Object value) [0x00000] in <filename unknown>:0 at Cirrious.MvvmCross.Binding.Bindings.MvxFullBinding.UpdateTargetFromSource (System.Object value) [0x00000] in <filename unknown>:0 

Se enlaza correctamente la primera vez – es sólo en las RaisePropertyChanged llamadas RaisePropertyChanged que esto ocurre. El mismo código también funciona en Windows 8 y Windows Phone.

Actualizar

El uso de JavaFinalise en el adaptador utilizado para el escenario anterior solucionó el problema (encontrado aquí: MVVMCross Binding Crashes Android Application ). El problema que tengo ahora es el mismo resultado, pero donde la primera vista de un adaptador está enlazada a una propiedad en el modelo de vista principal (no el elemento).

El código utilizado para enlazar es el siguiente:

 public class SubjectFilterAdapter : MvxAdapter { private EntityListFragment<TEntity, TViewModel> _owner; public SubjectFilterAdapter(Context context, EntityListFragment<TEntity, TViewModel> owner) : base(context, (IMvxAndroidBindingContext)owner.BindingContext) { _owner = owner; } protected override View GetBindableView(View convertView, object dataContext, int templateId) { var view = base.GetBindableView(convertView, dataContext, templateId); if (templateId == ItemTemplateId && GetPosition(dataContext) == 0) { var set = _owner.CreateBindingSet<EntityListFragment<TEntity, TViewModel>, TViewModel>(); set.Bind(view.FindViewById<TextView>(Resource.Id.SelectedScheduleText)) .To(x => x.SelectedScheduleText).WithClearBindingKey("SelectedScheduleTextFilterBinding"); set.Apply(); } return view; } protected override void JavaFinalize() { if (this.BindingContext != null) this.BindingContext.ClearAllBindings(); base.JavaFinalize(); } } 

Funciona correctamente para empezar (para el primer par de cambios), pero después de que la excepción anterior se lanza. Utilizando MvvmCross 3.0.14-beta3 .

¡Gracias!

Al mezclar los contextos de vinculación de listitem / célula con el contexto padre, estás entrando en un área bastante avanzada.

Para ayudar a intentar explicar / depurar lo que está pasando, es necesario comprender un poco acerca de todo el ciclo de vida de los padres, el ciclo de vida de listitem / célula y los ciclos de vida de los contextos de enlace MvvmCross correspondientes.

En el nivel de ciclo de vida de los padres, generalmente se trata de una Activity o Fragment Android. Para simplificar, utilizaré Activity para el resto de esta respuesta.

Esta Activity tiene un par de eventos clave del ciclo de vida

  • OnCreate se llama una sola vez cuando se lanza la Activity
  • OnDestroy se llama una sola vez cuando la Activity no se mostrará de nuevo.

MvvmCross intercepta estos eventos y:

  • Dentro de OnCreate , establece un ViewModel como ViewModel la Activity . Código de usuario – normalmente código Xml inflado dentro de SetContentView – a continuación, crea enlaces. Estos enlaces se almacenan dentro del BindingContext de la Activity
  • Dentro de OnDestroy , MvvmCross destruye todos los enlaces dentro de BindingContext

En la interfaz de usuario que nos interesa aquí, la Activity posee un ListView , y que ListView tiene un Adapter configurado para él. Dentro de este escenario, el DataContext para el ListView y su Adapter es el mismo como su padre.

Dentro de la vida útil de ListView la lista puede necesitar mostrar un montón de elementos. Los elementos que se muestran en cualquier momento pueden cambiar, tanto por las acciones táctiles del usuario como por los cambios del modelo de vista. Para mostrar estos elementos, el ListView le pregunta al Adapter para View . Para cada elemento se muestra que el Adapter suministra una View , y estas View pueden ser reutilizadas (utilizando el parámetro convertView ). Sin embargo, a veces, estas View también no se reutilizan; en esta situación, a veces es posible que el objeto Ver permanezca en C # incluso después de que se haya quitado Java / Dalvik View se haya finalizado Java.

MvvmCross intercepta las llamadas GetView dentro de su MvxAdapter . Para cada llamada no devuelve sólo una View pero además y MvxListItemView . Esta es una View con un BindingContext añadido – y esto permite a los usuarios de MvvmCross vincular cada MvxListItemView a su elemento de lista DataContext .

Cuando se MvxListItemView utilizar un MvxListItemView , es sencillo para MvvmCross cambiar simplemente su DataContext .

Cuando un MvxListItemView no se reutiliza – cuando se quita de la interfaz de usuario y, a continuación, JavaFinalize d – MvvmCross intercepta el evento OnDetachedFromWindow y utiliza esto para cambiar el DataContext a null . Esto se hace en OnDetachedFromWindow lugar de JavaFinalize como la llamada a la ventana se garantiza que se haga en el hilo de interfaz de usuario y como se siente (a mí) como un lugar más limpio para hacer esto.

Tenga en cuenta que parte de este comportamiento ha cambiado sutilmente en versiones recientes, pero esta descripción anterior es correcta para v3.0.14


Con ese fondo en su lugar, lo que parece que está intentando hacer es crear un enlace para el contenido de un ListItemView dentro del BindingContext de la Activity .

Esto significa que el enlace no tiene realmente una buena comprensión del ciclo de vida de ListItemView – por lo que el enlace puede decir vivo incluso después de que el ListItemView ha sido eliminado de la pantalla y (tal vez) finalizado.

Para resolver este problema …

  • Creo que la ruta más simple es cambiar el DataContext para su listitem. Si su enlace ListItemView es un simple enlace normal – si contiene la propiedad MinutesRemaining – entonces no debe golpear estos errores del ciclo de vida.
  • Usted puede intentar el enlace avanzado encontrado en la respuesta de @ Jamie ( https://stackoverflow.com/a/20031690/373321 ) – sin embargo, creo que esta respuesta todavía no lo entiendo bien – como creo:
    • No maneja correctamente el caso donde el listitemview se quita / finalizó – si el primer artículo de la lista se desplaza fuera de pantalla bajo el código actual entonces creo que todavía puede ver problemas. Para utilizar el adaptador de código basado, entonces creo que el adaptador necesita de alguna manera obtener una devolución de llamada desde el listitemview en el caso de que la vista se elimina de la interfaz de usuario o finalizado.
    • El JavaFinalize en esa respuesta es "un poco travieso" en que borra la Activity principal BindingContext durante la Finalize del Adapter . Esto es probablemente OK para hacer pero no debería ser realmente necesario – OnDestroy debe manejar eso.

Se corrigió actualizando el código del adaptador anterior a:

  public class SubjectFilterAdapter : MvxAdapter { private EntityListFragment<TEntity, TViewModel> _owner; private MvxFluentBindingDescriptionSet<EntityListFragment<TEntity, TViewModel>, TViewModel> _scheduleBindingSet; public SubjectFilterAdapter(Context context, EntityListFragment<TEntity, TViewModel> owner) : base(context, (IMvxAndroidBindingContext)owner.BindingContext) { _owner = owner; } protected override View GetBindableView(View convertView, object dataContext, int templateId) { var view = base.GetBindableView(convertView, dataContext, templateId); if (templateId == ItemTemplateId && GetPosition(dataContext) == 0) { if (_scheduleBindingSet != null) { _owner.BindingContext.ClearBindings("SelectedScheduleTextFilterBinding"); _scheduleBindingSet = null; } _scheduleBindingSet = _owner.CreateBindingSet<EntityListFragment<TEntity, TViewModel>, TViewModel>(); _scheduleBindingSet.Bind(view.FindViewById<TextView>(Resource.Id.SelectedScheduleText)) .To(x => x.SelectedScheduleText).WithClearBindingKey("SelectedScheduleTextFilterBinding"); _scheduleBindingSet.Apply(); } return view; } protected override void JavaFinalize() { if (this.BindingContext != null) this.BindingContext.ClearAllBindings(); base.JavaFinalize(); } } 
  • Componente inutilizable HockeyApp para Android (tienda de componentes Xamarin)
  • ¿Cómo puedo eliminar los idiomas no utilizados del archivo APK final con Xamarin.Android?
  • Cómo cambiar el color por defecto cuando el interruptor está "on" (azul a verde) en formas xamarin. En defecto del ios es GReen pero en androide es azul
  • ¿Debo usar MonoDroid o Android?
  • Desarrollo de iOS y Android en Windows
  • ¿Existe algún tipo de solución para desarrollar Blackberry Apps en C # como Mono para Android o Monotouch?
  • Registrar ContentObserver en Application.OnCreate () Servicio VS
  • ¿Cómo agregar una línea horizontal 1px encima de la vista de la imagen en un diseño relativo?
  • Xamarin FindViewById devuelve null
  • ¿Cómo hacer un intervalo de sombra de cadena en Android?
  • Xamarin construir acción de advertencia XA0101
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.