2 votes

Le thread d'arrière-plan bloque le WebView

J'injecte JavaScript à mon interface WebView et une fois que j'arrive à mes méthodes natives que j'ai définies dans le fichier JavaScript , si elle gèle le WebView jusqu'à ce que je renvoie une valeur. Par exemple :

Dans cet exemple, le WebView est bloqué pour le 8 secondes . J'ai également revérifié qu'il ne s'agit pas du thread principal, et ce n'est effectivement PAS le thread principal, donc je ne vois pas pourquoi cela gèlerait le thread principal. WebView .

myWebView.addJavascriptInterface( new WebViewHandler.JavaScriptInterface(), "webCallHandler" );

public class JavaScriptInterface
{
    @JavascriptInterface
    public String jsToAndroidNativeFunc(String Data)
    {

        Callable<String> task = new Callable<String>() {
            @Override
            public String call() throws Exception {
                try {
                    if( Looper.getMainLooper() == Looper.myLooper() )
                        Log.d("TAG","Main Thread");
                    else
                        Log.d("TAG","Not Main Thread");
                    TimeUnit.SECONDS.sleep(8); // the webview is now stuck during these 8 seconds
                    return "123";
                }
                catch (InterruptedException e) {
                    throw new IllegalStateException("task interrupted", e);
                }
            }
        };

        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<String> future = executor.submit(task);

        try {
            return future.get();
        }
        catch (InterruptedException e) {
            e.printStackTrace();
            return "111";
        } catch (ExecutionException e) {
            e.printStackTrace();
            return "111";
        }
    }
}

0voto

tamas rev Points 177

Mise à jour

Ce code est invoqué avec le code javascript suivant :

var response = webCallHandler.jsToAndroidNativeFunc(request.data);

C'est exactement ce qui fait que l'interface utilisateur se fige parce que Le javascript est à un seul fil d'Ariane . Nous devons faire des invocations asynchrones avec des callbacks. Tout comme Ajax.

Réponse originale

Je ne connais pas l'interface js Android. Ce que je sais, c'est que votre fonction attend une réponse. C'est à dire Future.get() est une fonction de blocage. Extrait de la [API](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()) :

Attend, si nécessaire, que le calcul soit terminé, puis récupère son résultat.

Je propose de faire ceci jsToAndroidNativeFunc void et ajouter un callback. Je suggère également de définir un exécuteur en dehors de la méthode. Par exemple, au niveau de la classe ou de l'application :

public class JavaScriptInterface
{

    private final ExecutorService EXECUTOR = Executors.newFixedThreadPool(1);

    @JavascriptInterface
    public void jsToAndroidNativeFunc(String Data, Callback callback)
    // I just made up the Callback class. There must be a way to do so with webview too.
    {

        Callable<String> task = new Callable<String>() {
            @Override
            public String call() throws Exception {
                try {
                    // ...
                    callback.call("123"); // no return, but call the js callback
                }
                catch (InterruptedException e) {
                    throw new IllegalStateException("task interrupted", e);
                }
            }
        };

        EXECUTOR.submit(task); // using the static executor
        // no Future, no return either. Js side will execute asynchronously.
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X