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