Dans le développement Android, nous utilisons souvent Handler
les classes fournies par le SDK Android pour mener à bien la tâche de communication inter-thread, mais dans le code du projet, nous voyons souvent qu'elles sont Handler
utilisées de manière trop désinvolte, et ces utilisations peuvent avoir des dangers cachés. article enregistre ces problèmes et donne des conseils connexes.
Question 1 : Utiliser la construction sans argument par défaut pour créer un gestionnaire
Handler
Il existe une méthode de construction sans argument, parfois paresseuse Activity
pour créer Handler
des objets directement via la méthode de construction sans argument, par exemple :
private final Handler mHandler = new Handler();
Ensuite, cet Handler
objet utilisera le thread actuel Looper
, ce qui Activity
peut convenir dans une vue personnalisée, car le thread principal existe Looper
, mais une exception se produira dans le sous-thread, car le sous-thread n'a probablement pas été exécuté Looper.prepare()
. Un autre danger caché est que l'on peut s'attendre à ce que new Handler()
l'utilisation du "thread actuel" soit dans le thread enfant, mais l'appel externe initial se trouve dans le thread principal, donc cette utilisation peut affecter l'expérience interactive du thread principal.Looper
- Conseil :
Handler
Les objets doivent être créés avecLooper
des arguments pour assurerLooper
leur existence et contrôler explicitement leur threading.
Problème 2 : Abus de Looper.getMainLooper()
Dans Activity, nous pouvons utiliser runOnUiThread
des méthodes pour exécuter un processus sur le thread principal, mais à d'autres endroits, le passage Looper.getMainLooper()
est également une méthode simple, par exemple :
new Handler(Looper.getMainLooper()).post(() -> {
//do something ...
});
Parce qu'il est si pratique, il peut être utilisé partout, il y a donc un danger caché : n'importe quel thread peut affecter le thread principal de cette manière. Des gels inattendus peuvent se produire sur les téléphones mobiles avec une mauvaise configuration, et ce type de gel peut être aléatoire et difficile à reproduire, ce qui rend difficile la résolution des problèmes.
- Suggestion : évitez de créer le fil en dehors du fil
Handler
, par exemple, essayez d'éviter de créer le fil principal à des endroits autres queActivity
,Fragment
et une vue personnaliséeHandler
.
Question 3 : Créer un gestionnaire directement au niveau de la fonction métier
En développement, vous devez parfois l'utiliser Handler
pour changer de thread, ou utiliser Handler
la fonction de message, puis l'utiliser directement Handler
, comme le code suivant :
new Thread(() -> {
presenter.doTaskInBackground();
new Handler(Looper.getMainLooper()).post(() -> {
updateViewInMainThread();
});
}).start()
Il y a trop de slots dans ce code, donc je vais surtout en parler ici Handler
. En fait, il n'y a rien à redire sur le résultat du programme. Le défaut est que Handler
ce concept lié à la plate-forme est mélangé dans le code de la fonction commerciale, comme si une personne lisait un poème et récitait "deux loriots chantant des saules verts", et puis apparaît ci-dessous Dites "Je vais d'abord prendre une gorgée d'eau", après avoir bu l'eau, continuez à lire.
- Suggestion : Placez
Handler
la création et la destruction de l'objet au niveau du framework, et même encapsulez un ensemble d'interfaces utilisées au lieu d'utiliser directementpost
et etsend
d'autres méthodes.
Problème 4 : Le message et le rappel de Hanlder n'ont pas été supprimés à temps
Handler
et sont deux méthodes pratiques, mais cette méthode n'est pas liée au cycle de vie du composant, qui peut facilement provoquer ou d'autres objets volumineux postDelayed
qui ne peuvent pas être libérés à temps.postAtTime
Activity
- Suggestion
removeCallbacksAndMessages
: Appelez la méthode à temps lorsque vous n'en avez pas besoin