web-dev-qa-db-fra.com

Gonfler une vue dans un fil de fond

J'ai une question très simple:

Est ou n'est-il pas possible de gonfler une vue (non pas ajouter à la mise en page) dans un fil d'arrière-plan (ex: dans le doInBackground d'un AsyncTask)?

Je sais que cela est possible, car j'ai mis en œuvre la plupart des activités de mon application de cette façon et que je n'ai jamais eu de problème, jusqu'à ce que j'ai eu ce problème sur une galaxie S: Android: Android.View.inflateException: Ligne de fichier XML binaire # 13: erreur de gonflage de la classe <inconnue> à Samsung Galaxy S

On m'a dit que je devrait PAS gonfler Views dans des threads d'arrière-plan, mais quelles sont les raisons spécifiques et pourquoi mon APRAPOCH fonctionne-t-il dans la plupart des appareils, mais pas à Galaxy S?

35
pandre

Le LayoutInflater ne fait aucune hypothèse sur quel thread il fonctionne. Et rien n'est mentionné dans sa documentation. Aussi ses coutures de code pour être thread-agnostiques.

D'autre part, des vues créées par LayoutInflater peuvent instancier Handlers dans leurs constructeurs. Eh bien, ils ne devraient probablement pas faire cela, mais il n'est pas nécessaire de ne pas créer/utiliser Handlers dans leurs constructeurs.

Je suppose que Samsung Galaxy S avait quelques modifications dans son EditText _ qui déclenche une manière en quelque sorte création de Handler (selon le journal des crash de votre autre instance de questions de GestureDetector a été instancié. Tournez créé Nouveau Handler). Tandis que la mise en œuvre par défaut ne fait pas cela.


Dans l'ensemble, je dirais que, car il n'y a pas d'exigence explicite pour Views à ne pas utiliser Handlers et Loopers dans leurs constructeurs, vous ne pouvez pas supposer une vue gonflée de non-UI. Le fil est sûr.

Vous pouvez réellement créer HandlerThread et essayez gonfler Views à l'intérieur. Mais je dirais que cela est très risqué, comme dans l'exemple de Samsung Galaxy S, la vue suppose que ce fil sera en vie pendant View vietime et traitera tous les messages à l'aide de son Looper. Ce qui pourrait entraîner une crash plus tard.

40
inazaruk

Avec le dernier support que vous pouvez utiliser Android.support.v4.view.AsyncLayoutInflater Pour gonfler des vues de manière asynchrone. Soyez prudent que cela puisse revenir à gonfler sur le fil de l'interface utilisateur si des exigences spécifiques ne sont pas remplies:

Pour qu'une mise en page soit gonflée de manière asynchrone, il doit disposer d'un parent dont les produits de sécurité de GeneratelayOntParams (attributset) sont en sécurité et que toutes les vues étant construites dans le cadre de l'inflation ne doivent pas créer de gestionnaires ni appeler mylooper (). Si la mise en page qui tente d'être gonflée ne peut pas être construite de manière asynchrone pour une raison quelconque, AsynclayOnflater reviendra automatiquement à gonfler sur le fil de l'interface utilisateur.

14
M-WaJeEh

Est-il ou n'est-il pas possible de gonfler une vue (ne pas l'ajouter à la mise en page) dans un fil d'arrière-plan (ex: dans le domaine doinback d'un système d'asyncaptage)?

Possible, oui. Conseillé? Non, comme mentionné dans la documentation:

Ainsi, il y a simplement deux règles au modèle de thread unique d'Android:

  1. Ne bloquez pas le fil de l'interface utilisateur
  2. N'accédez pas au Android Toolkit UI de l'extérieur du fil d'interface utilisateur

vIA: processus et threads

Mise à jour [02/06/19]:

Apparemment, la bibliothèque de support a un outil pour le faire: asynclayoutinflater ( version jetpack ). Il a été introduit dans la version 24, vers 2016 (2 ans après ma réponse)

Mais comme mentionné sur d'autres réponses, soyez prudent avec cet outil car il peut très facilement faire feu à la contre-feu.

4
pablisco