J'ai un problème avec ce code dans lequel la relève Comment puis-je résoudre ce problème sans utiliser Ceci est la classe de stockage p> appelant stockage d'une interface p> J'ai également essayé la solution de r2rek et obtenir le même résultat P> retourne code> est déclenchée avant que la fonction
OngetstatsCompleted code> fonctionne et renvoie 0 au lieu de la bonne valeur.
Existe-t-il une façon de forcer
ongetstatatsCompletd code> pour terminer avant de retourner
packages sur code>?
Je sais que c'est un problème logique parce que si je supprimais le commentaire à
// thread.sleep code> Ça fonctionne bien.
thread.sleep code> ou toute autre sorte de temps dans l'application?
code d'origine: strong> p>
try {
GlobalScope.launch(Dispatchers.Main){
var getPackageSizeInfo = withContext(coroutineContext) {
pm.javaClass.getMethod(
"getPackageSizeInfo", String::class.java, IPackageStatsObserver::class.java)
}
getPackageSizeInfo.invoke(pm, context.packageName,
object : CachePackState() {//Call inner class
})
}
} catch (e: Exception) {
e.printStackTrace()
}
}
return packageSize
4 Réponses :
Je vous recommande vivement de faire ce travail sur le fil d'arrière-plan en utilisant Rxjava, Coroutines ou AsyncCTTK. Mais vous pouvez utiliser un contextdownlatch pour faire une solution rapide.
//Ugly global variable val countdownLatch = CountdownLatch(1) //-------CHANGE HERE-------- /** Get the size of the app for API < 26 */ @Throws(InterruptedException::class) fun getPackageSize(): Long { val pm = context.packageManager try { val getPackageSizeInfo = pm.javaClass.getMethod( "getPackageSizeInfo", String::class.java, IPackageStatsObserver::class.java) getPackageSizeInfo.invoke(pm, context.packageName, object : CachePackState() {//Call inner class }) } catch (e: Exception) { e.printStackTrace() } countDownLatch.await(1_000, TimeUnit.MILLISECONDS) //-------CHANGE HERE-------- return packageSize } /** Inner class which will get the data size for the application */ open inner class CachePackState : IPackageStatsObserver.Stub() { override fun onGetStatsCompleted(pStats: PackageStats, succeeded: Boolean) { //here the pStats has all the details of the package dataSize = pStats.dataSize cacheSize = pStats.cacheSize apkSize = pStats.codeSize packageSize = cacheSize + apkSize countDownLatch.countDown() //-------CHANGE HERE-------- } }
Je ne veux pas utiliser un compte à rebours non plus, mais je vais essayer d'utiliser l'asyncaptage
Utilisation du thread.sleep (..) n'est pas seulement non seulement recommandé, il peut également verrouiller l'interface utilisateur et ne pas produire le résultat que vous souhaitez (si la méthode GetPackagesizeInfo fonctionne de plus de 1 seconde).
Je suggère fortement d'obtenir des informations sur le fil d'arrière-plan, à l'aide de l'asyncaptage ou de la Corouté, comme @ Luciano-Ferruzzi suggéré. Puisque vous utilisez déjà Kotlin, j'irais une solution natale et utilisez des coroutines, ce qui pourrait ressembler à quelque chose comme ceci: Comme vous pouvez le constater, cela ne fait pas de modification de votre code. , à l'exception de manière explicitement indiquant les threads que vous utiliseriez pour des parties spécifiques du code. P> * Désolé pour toutes les erreurs de code, je ne l'ai pas vraiment compilé. p> p>
Cela retourne toujours 0, j'ai mis à jour la question pour montrer ce que j'ai fait
Le moyen le plus simple consiste à utiliser Kotlin Coroutines A > et leurs fonctions de suspension. Démarrer par Ajout eux à votre projet P> //wherever you want to get size
....
getPackageSize(::handlePackageSize)
....
fun handlePackageSize(size: Long) {
//do whatever you want with size
launch(Dispatchers.Main) {
findViewById<TextView>(R.id.textView).text = "APP SIZE= $size"
}
}
Cela semble être une solution possible. Je reçois des répartiteurs de référence non résolus et je ne trouve pas l'importation. J'ai aussi kotlin.coroutines = activer code> dans gradle.properties. Est-ce que tu sais pourquoi?
@ Phil652 Avez-vous ajouté Coroutines à votre projet? Github.com/kotlin/kotlinx.coroutines#gradle Partie principale et Android
Vous devriez être capable d'accéder à kotlinx.coroutines.dispatchers code> si vous avez ajouté une dépendance correctement
@ Phil652 Yep, je viens de vérifier la combinaison de la kotlinversion = 1.2.61 et de Coroutintinesversion = 1.2.1 fonctionne bien. Pouvez-vous montrer quelle dépendance kotlin utilisez-vous?
J'ai ajouté la mise en œuvre 2 pour les Coroutines de ma build.Gradle. Les répartiteurs sont résolus mais je reçois référence non résolue. Aucun des candidats suivants n'est applicable en raison du type de récepteur Mismatch: Fun Public Fun Coroutinescope.Launch (Contexte: COROUTINECONTEXT = ..., Démarrer: COROUTINESTART = ..., Bloc: Suspendez Coroutinescope. () → Unité): Job défini à Kotlinx .Coroutine code> et
'withContext (COROUTINECONTEXT, Suspend Coroutinescope. () -> T): T' n'est disponible que depuis Kotlin 1.3 et ne peut pas être utilisé dans Kotlin 1.2 Code>
@ Phil652 met à jour à Kotlin 1.3 quelque chose que vous ne pouvez pas faire? Parce que ce que j'ai proposé suit le guide fourni par l'équipe de Kotlin. Par exemple, ici Medium.com/@elizarov/coroutine-Context-and-scope- C8B255D5905 5
Je travaille actuellement sur cela sur une autre succursale, mais ce n'est pas encore prêt. Donc non pas pour le moment, mais je me mettrai à la mise à jour de Kotlin 1.3 dans un proche avenir
@ Phil652 J'ai découvert de savoir quel était votre problème si vous ne voulez pas mettre à niveau la version de Kotlin, vous devez utiliser une version très ancienne Version Coroutin Signification 0.30.2 Code> pour le noyau et l'Android. Ensuite, cela fonctionnera comme décrit
J'ai déjà eu api "org.jetbrains.kotlinx: kotlinx-coroutines-android: 0.22.5" code> dans mon build.gadle comme une dépendance, est-il possible que cela provoque des problèmes lors de l'ajout de noyau de coroutine et Android
J'ai réussi à mettre en œuvre des coroutines de mon projet, j'ai mis à jour ma question avec le code actuel. J'ai toujours 0. Qu'est-ce que je fais mal?
Dans votre fonction de non-suspension, vous retournez 0, c'est la raison. Vous affectez la taille: long = 0; Ensuite, vous passez à un fil différent (à l'intérieur est exécuté sur un fil différent), puis vous retournez 0 car cela n'attend pas le résultat et vous ne voulez pas que cela attend. Vous pouvez soit marquer cette fonction comme suspension, puis quand vous avez besoin de résultat, appelez-le à l'intérieur E.g lancement code>. En vous case, vous pouvez simplement déplacer
val appsifiés = formatfilesize (getApplicationContextex (), getPackagesize ()) code> à l'intérieur du
globalscope.launch (Dispatchers.io) { code> et avez-vous l'action là.
Merci pour votre aide, il est utilisé dans un modèle de messagerie afin que je ne puisse pas vraiment mettre à jour l'interface utilisateur à l'intérieur du globalscope.launch (Dispatchers.io) { code> Y a-t-il un moyen de le faire en modifiant simplement une variable à l'intérieur du coroutinécope. Je peux ajouter plus de mon code si nécessaire
Je met à jour ma question avec quelque chose d'autre que j'ai essayé, je n'ai toujours aucune valeur
@ phil652 j'ai mis à jour la réponse montrant comment le gérer différemment
Avec ce module, je reçois avec le répartiteur principal est manquant code>. Cela pourrait être parce que j'utilise une version plus ancienne
@ Phil652 Avez-vous des corouts Android Dépendances?
C'est une école assez ancienne mais que diriez-vous:
while(packageSize < 0) { Thread.sleep(100) }
Jusqu'à présent, c'est la seule solution de travail. Je ne sais tout simplement pas si c'est une bonne solution, WHIP.Sleep bloque un fil et de ce que j'ai appris que la meilleure pratique consiste à rester loin d'eux. Je pourrais avoir tort, je suis toujours très nouveau à Kotlin. Aussi, cela pourrait devenir une boucle infinie si pour une raison quelconque des paquets est toujours <0
1) thread.sleep code> est une fonctionnalité de base Java de base, donc je suis curieux de vos "meilleures pratiques". Vous rencontrez une condition de course si une sorte de coordination de fil est requise. 2) Si
packages sur code> peut toujours rester négatif, c'est absolument une préoccupation que vous devrez aborder. Vous pouvez utiliser l'approche
CountownTownLatch CODE> qui est essentiellement la même chose avec un peu plus de machines et vous permet d'attendre de manière conditionnelle avec
attendre (délai d'attente longue, unité TimeUnit) code>
@Davidsoroko Vous recommandez-vous sérieusement de bloquer l'interface utilisateur pour 100ms ?!
Je ne recommande pas de valeur particulière pour le sommeil, le code sera correct de la durée ou sans sommeil si la filature de la CPU n'est pas une préoccupation.