Spanish La "importancia" de algo tan aparentemente insignificante como un Sleep(0)

Gabino A. de la Gala

Active Member
Licensed User
Longtime User
Quizás para muchos de vosotr@s ésto que voy a decir os parezca algo de "cajón", pero a mi me ha costado un par de horas darme cuenta de la sutil diferencia:

Estaba intentando implementar el SwipeToRefresh en una clv. Pero no quería que el tiempo en el que aparece el panel con el progressbar, etc fuera un tiempo fijo, sino que dura lo que realmente tardara el tiempo en el que se rellenaba la clv.

Para ello, yo llamaba al procedimiento de RellenarClv y "pensaba" que hasta que no acabara el proceso, no se haría la llamada al Swipe.RefreshCompleted pero naranjas de la china. Se me ejecutaba en "paralelo", con lo cual, en medio segundo me desaparecía el panel.

El código que yo estaba utlizando era:

B4X:
Sub Swipe_RefreshRequested
	lblPullToRefresh.Text = "Cargando..."
	ProgressBarSwipe.Visible = True
	
	Sleep(500)
	
	RellenarClv
	
	Swipe.RefreshCompleted '<-- call to exit refresh mode
	lblPullToRefresh.Text = "Tirar para refrescar..."
	ProgressBarSwipe.Visible = False
End Sub

Pues después de estar un buen rato dándome cabezazos con ello me di cuenta que el "problema" venía dado porque dentro del RellenarClv había un "inocente" (por llamarlo de alguna manera agradable) Sleep(0).

Al llamar al sleep(0), el procedimiento se convierte de manera automática en resumable, con lo cual para que la aplicación se quede esperando a que acabe, hay que cambiar la manera de llamarlo y adicionalmente, convertirlo en una función que devuelva algo que luego puedas utilizar.

Así que el código de llamada finalmente me quedó así:

B4X:
Sub Swipe_RefreshRequested
	lblPullToRefresh.Text = "Cargando..."
	ProgressBarSwipe.Visible = True
	
	Sleep(500)
	
	wait for (RellenarClv) complete (nReg As Int)
	
	Swipe.RefreshCompleted '<-- call to exit refresh mode
	lblPullToRefresh.Text = "Tirar para refrescar..."
	ProgressBarSwipe.Visible = False
End Sub

Y el RellenarClv quedó algo así;

B4X:
Sub RellenarClv As ResumableSub
    Dim l As List
    I = Tracker.kvs.Get("EventList")
    If l.IsInitialized Then
		Dim i As Int
		CustomListView1.Clear
		For i = l.Size-1 To 0 Step -1
			Log(i)
                        Dim event As tEvent
			event.Initialize
			event = l.Get(i)
   ... 
   ... 
   ... 
                      CustomListView1.Add(p, Swipe.CreateItemValue(event, Array("Delete1", "Action 2", "Action 3")))
               Next
      End If
  Return I.size

End Sub
 
Asi es, también podes usarlo en todo el arranque de la app, colocándolo con una variable dentro como parámetro, salteado dentro de la app, entonces cuando en testeo tenes un crasheo importante donde ni siquiera logra mostrar la app después de abrirla, cerrándose instantáneamente, por lo menos podes que va haciendo en secuencia, dándole a ese parámetro dentro del sleep, algo como 200 ms. Y cuando lo sacas en modo release para producción y ya no en testeo, pones ese parámetro dentro del sleep como = 0. Te da una idea de en que parte hace el error. Me ha pasado que ni siquiera lograba mostrase la app.

Ej:
globals:
Sub Globals

...

    'Parametros de sistema

      Private demora = 0 As Int

End sub

activity:
Sub Activity_Create(FirstTime As Boolean) 'ignore

...

      'operaciones varias 1



'Log("operaciones varias 1 realizadas")   
Sleep(demora)   


      'operaciones varias 2



'Log("operaciones varias 2 realizadas")   
Sleep(demora) 


      'operaciones varias 3



'Log("operaciones varias 3 realizadas")   
Sleep(demora) 


      'operaciones varias 4



'Log("operaciones varias 4 realizadas")   
Sleep(demora) 


End sub


*** Con respecto al sqlite + clv + progressbar con un sleep(1) ya alcanza a refrescar toda la parte visual sin tildar ni congelar la app. Saludos desde Argentina!
 
Top