Ответ 1
Я хочу знать, что если есть время, прежде чем я могу получить доступ к моему объекту
Да, я думаю, что есть задержка, потому что WebView.addJavascriptInterface
будет запущен в внутреннем рабочем потоке WebView. Возможно, вы об этом подумали и поняли, что WebView должен поддерживать по крайней мере один рабочий поток для выполнения асинхронной сетевой операции ввода-вывода. Возможно, вы также заметили эти потоки в DDMS при использовании WebView.
Оказывается, он также использует поток для работы для ряда других общедоступных методов. Я очень хочу, чтобы документы Google сделали это яснее! Но я надеюсь, что смогу помочь и показать вам, как я пытался подтвердить это для себя.
Следуйте за мной, когда я взгляну на источник для WebView. Это разумно читаемо, даже если вы не можете точно следить за тем, что происходит, можно проследить ответы на некоторые вопросы относительно потоков.
Вы можете загрузить исходный код Android с помощью инструмента менеджера SDK, но он также отразился на Github, так что я связался здесь. Я догадался и выбрал тег, близкий к некоторой версии ICS. Нетрудно найти WebView.addJavascriptInterface
. Я просто Googled "WebView.java сайт: github.com/android".
Метод WebView.addJavascriptInterface
отправляет сообщение экземпляру WebViewCore
:
mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
В WebViewCore.java
есть множество перегруженных методов, называемых sendMessage
, но нам не нужно знать, что именно вызывается, поскольку они делаю почти то же самое. Там даже хороший комментарий, чтобы дать нам намек, что мы в нужном месте! Все они делегируют экземпляр EventHub
, который является некоторым внутренним классом. Этот метод оказывается синхронизированным и отправляет сообщение в экземпляр Handler
, что является хорошим показателем того, что это, вероятно, работает в другом потоке, но для полноты, давайте узнаем!
Этот Handler
создается в EventHub.transferMessages
, который вызывается из WebViewCore.initialize
. Здесь есть еще несколько прыжков, но в конце концов я узнал, что это вызвано из run
в WebCoreThread
(подкласс Runnable
), который создается вместе с новым Thread
правом .
Какое приключение! Поэтому, хотя я действительно не могу точно сказать, что происходит со всеми этими движущимися частями, я уверен, что этот метод не является синхронным и отправляет сообщение в рабочий поток WebView. Надеюсь это имеет смысл!
Если да, как узнать, сколько времени мне нужно подождать, чтобы вызвать мой объект?
К сожалению, я не знаю ответа на этот вопрос. Я изучал этот точный вопрос и нашел этот вопрос в StackOverflow в ходе моего Googling. Я думаю, у вас есть следующие варианты, некоторые из которых лучше или проще других:
1) Просто Thread.sleep
за 100 мс или что-то среднее между addJavascriptInterface
и loadUrl("javascript:...")
. Блех, мне это не нравится, но это, возможно, самый простой.
2) Еще одна возможность состоит в том, что вы могли бы вызвать WebView.loadUrl
со фрагментом JavaScript, который специально проверяет, установлен ли интерфейс, и улавливает возвращаемое ReferenceError, если оно еще не установлено. Однако, как вы, возможно, догадались, это связано с добавлением интерфейса JavaScript в WebView!
3) Вместо этого вызовите WebView.setWebChromeClient
и перехватите JavaScript alert()
или console.log
. Из моих экспериментов этот метод синхронный, поэтому нет задержки. (Я подтвердил это в источнике, но я оставлю детали как упражнение для читателя). Вероятно, вы должны найти специальную строку для вызова alert
с и проверить ее внутри onJsAlert
, так что вы не просто ловите все alert()
s.
Извините за длину этого ответа, надеюсь, это поможет. Удачи!