12
votes

Après un certain temps d'utilisation, mon app gèle lors du défilement d'une vision webview, disant "ne pouvait pas verrouiller la surface"

Mon application Android comprend plusieurs activités, chacune responsable d'un seul fragment (pour l'instant). Mes fragments sont généralement affichés / attachés quelque peu comme suit:

mWebView = (WebView)getView().findViewById(R.id.topic_webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
mWebView.getSettings().setAllowFileAccess(true);
mWebView.addJavascriptInterface(mJsInterface, "api");
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.loadData("", "text/html", "utf-8");
mWebView.setBackgroundColor(0x00000000);


0 commentaires

3 Réponses :


2
votes

Je suppose que je l'ai réparé. Apparemment, il existe un bogue qui empêche la gestion de la mémoire correcte de la View. Lorsque je démarre de nombreuses activités avec webview sous leurs vues, les vues Web vivent dans la mémoire et les activités ne sont pas correctement tuées lorsque la mémoire fonctionne bas. J'ai travaillé autour de la question avec le code suivant dans mon Topicfragment qui affiche le webview : xxx

de cette façon, le webview est créé et supprimé dans OnResume et Ensuite . Ceci est des frais généraux et non parfaits, mais cela résout le problème de la mémoire et est à peine notable en termes de performance et ainsi de suite.


2 commentaires

Cette approche a résolu mon problème similaire, mais notez que la documentation de l'API pour webview.destroy déclare que cela devrait être appelé après que la vue a été supprimée du système d'affichage, alors que votre interrupation l'appelle avant d'avoir été supprimée du conteneur.


Merci c'est noté. Cependant, je suis toujours insatisfait de cette solution car elle introduit un scintillement notable et quelque peu mal l'expérience utilisateur.



0
votes

Si vous avez de nombreux webviews dans votre application dans différentes activités / fragments que vous pouvez essayer d'utiliser un pool dans lequel vous pouvez récupérer une instance WebView dans la méthode Activé Oncree () et remettez à la piscine sur la piscine dans Activestory ( ).

La taille WebViewPool peut être configurée par classe de mémoire de périphérique d'utilisateurs. Cela peut ne pas être la meilleure solution pour chaque application utilisant Webviews, mais sa solution que vous pouvez envisager. Vous avez peut-être besoin de tests, etc.

Mais gardez à l'esprit, les objets dans une piscine ne sont pas recueillis, alors faites attention si vous décidez d'utiliser une piscine.


1 commentaires

Bonjour Sockeqwe, j'ai envisagé cette option (ou, en fait, pour conserver une vision Web unique quelque part et la réutiliser tout le temps). Cependant, comme je l'ai décrit dans ma réponse, il semble plus intelligent de créer et de détruire de nouveaux webviews si nécessaire, je n'ai donc pas à réfléchir aux exigences et aux ressources de la mémoire.



0
votes

J'ai finalement trouvé le problème. Éteindre l'accélération matérielle pour la visualisation WebView résolvère.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) {
    //...
    if (Utils.isKitkat()) {
        disableHardwareAcc();
    }
    //...
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
protected void disableHardwareAcc() {
    mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}


1 commentaires

J'ai vu d'autres choses "fixes" en éteignant l'accélération matérielle, mais je ne le recommande pas parce que l'expérience utilisateur devient lente et des animations sont chunky.