Quiero saber que si hay algo de tiempo antes de que pueda acceder a mi objeto
Sí, creo que hay un retraso, porque WebView.addJavascriptInterface
se ejecutará en el subproceso de trabajo interno de la vista Web. Tal vez haya pensado en esto y se haya dado cuenta de que WebView debe mantener al menos un hilo de trabajo para hacer IO de red asíncrona. Quizás también haya notado estos hilos en DDMS al usar un WebView.
Resulta que también utiliza un hilo para trabajar con otros métodos públicos. Realmente deseo que los documentos de Google lo aclaren. Pero espero poder ayudarte y mostrarte cómo intenté confirmar esto por mí mismo.
Sígueme cuando eche un vistazo a la fuente de WebView. Es razonablemente legible, incluso si no puede seguir exactamente lo que está sucediendo, es posible rastrear a través de la respuesta algunas preguntas con respecto a los hilos.
Puede descargar la fuente del marco de Android a través de la herramienta del administrador de SDK, pero también se refleja en Github, así que eso es lo que he vinculado aquí. Adiviné y elegí una etiqueta que está cerca de alguna versión de ICS. No es difícil encontrar . Acabo de buscar en Google "WebView.java site: github.com/android".
El método WebView.addJavascriptInterface
envía un mensaje a una instancia de WebViewCore
:
mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
En WebViewCore.java
hay un montón de métodos sobrecargados llamados sendMessage
, pero que en realidad no necesitamos saber exactamente lo que se está llamando, ya que hacen más o menos lo mismo. ¡Incluso hay un buen comentario para darnos una pista de que estamos en el lugar correcto! Todos ellos están delegando a una instancia de EventHub
que es una clase interna. This method resulta estar sincronizado, y está enviando un mensaje a una instancia de Handler
, lo cual es una buena indicación de que esto probablemente se está ejecutando en otro hilo, pero, para más información, ¡descubramos!
Eso Handler
se instancia en EventHub.transferMessages
que se llama desde WebViewCore.initialize
. Hay algunos saltos más aquí, pero finalmente descubrí que esto se llama desde run
en WebCoreThread
(subclase de Runnable
), que se crea una instancia junto con un nuevo Thread
derecho here.
¡Qué aventura! Entonces, aunque realmente no puedo decir con certeza qué está pasando con todas estas partes móviles, estoy bastante seguro de que este método no es síncrono y envía un mensaje al hilo de trabajo de WebView. ¡Espero que tenga sentido!
si es así, ¿cómo puedo saber cuánto tiempo debo esperar para llamar a mi objeto?
Lamentablemente, no sé la respuesta a esto. Estaba investigando este problema exacto y encontré esta pregunta en StackOverflow durante mi búsqueda en Google. Creo que tiene las siguientes opciones, algunas de las cuales son más agradables o más fáciles que otras:
1) Solo Thread.sleep
durante 100 ms o algo entre addJavascriptInterface
y loadUrl("javascript:...")
. Blech, no me gusta esto, pero es potencialmente el más fácil.
2) Otra posibilidad es que pueda llamar al WebView.loadUrl
con un fragmento de JavaScript que prueba específicamente si la interfaz está configurada, y capta el error de referencia que se lanza si aún no está configurado. Sin embargo, como habrás adivinado, ¡esto implica agregar una interfaz de JavaScript a WebView!
3) Llame WebView.setWebChromeClient
en su lugar, y capture JavaScript alert()
o console.log
en su lugar. De mis experimentos, este método es síncrono, por lo que no hay demora. (He confirmado esto en la fuente, pero dejaré los detalles como un ejercicio para el lector). Probablemente deberías encontrar una secuencia especial para llamar al alert
y verificarla dentro de onJsAlert
, por lo que no solo estás atrapando todos alert()
s.
Disculpa la duración de esta respuesta, espero que ayude. ¡Buena suerte!
Buena respuesta elaborada con referencias apropiadas. –
genial. buena respuesta. Pero revisar las alertas y los mensajes de la consola son tan malos como hacer Thread.sleep() :) – Akshat
Oye, todos advertí que las opciones son subóptimas: P – spacemanaki