2010-03-21 6 views
3

J'écris une application android qui dessine directement sur le canevas de l'événement onDraw d'une vue.Dessin sur le canevas

je dessine quelque chose qui implique dessiner chaque pixel individuellement, pour cela, j'utiliser quelque chose comme:

for (int x = 0; x < xMax; x++) { 
    for (int y = 0; y < yMax; y++){ 
    MyColour = CalculateMyPoint(x, y); 
    canvas.drawPoint(x, y, MyColour); 
    } 
} 

Le problème ici est que cela prend beaucoup de temps à peindre la routine CalculateMyPoint est tout à fait un cher méthode.

Existe-t-il un moyen plus efficace de peindre sur le canevas, par exemple devrais-je dessiner sur une image bitmap puis peindre tout l'image bitmap sur le canevas de l'événement onDraw? Ou peut-être évaluer mes couleurs et remplir un tableau que la méthode onDraw peut utiliser pour peindre la toile?

Les utilisateurs de mon application pourront modifier les paramètres qui affectent le dessin sur le canevas. C'est incroyablement lent en ce moment.

+0

Qu'est-ce qui rend le processus de CalculMyPoint si long? – Adam

+0

J'ai un calcul raisonnablement impliqué pour calculer une couleur à utiliser pour un pixel donné. Je me demande simplement s'il est préférable de calculer la couleur pour chaque pixel d'autre où au lieu de dans l'événement onDraw de la vue. – Mattl

+0

Avez-vous besoin de dessiner chaque pixel individuellement? Parce que c'est plus de 400k pixels sur un Droid ou un Nexus et je pense qu'il y a plus d'opportunité d'optimiser le nombre d'appels de CalculateMyPoint que dans son runtime. – jqpubliq

Répondre

5

Comme les gens l'ont souligné, si CalculateMyPixel() est cher, avoir ce qu'on appelle 150 000 (HVGA) ou 384,00 fois (WVGA) va juste vous tuer. En plus de cela, essayer de dessiner votre interface utilisateur sous forme de pixels individuels via canvas.drawPoint() chaque fois qu'il y a une mise à jour est à peu près le moyen le moins efficace.

Si vous dessinez des pixels individuels, vous voulez certainement avoir une sorte de bitmap hors écran contenant les pixels que vous dessinez avec un simple Canvas.drawBitmap(). Ensuite, vous pouvez choisir la meilleure façon de gérer cette image bitmap. La plus simple consiste simplement à créer un objet Bitmap de la taille souhaitée et à utiliser les API pour le remplir.

Alternativement, il existe une version de drawBitmap() qui prend un tableau d'entiers bruts, donc vous pouvez le remplir directement avec les valeurs que vous voulez, en évitant un appel de méthode pour chaque pixel.

Vous pouvez maintenant déplacer votre calcul de pixels à l'aide de la méthode onDraw(), qui doit être rapide pour avoir une interface utilisateur réactive, et remplir vos pixels ailleurs. Peut-être que vous les calculez une fois au moment de l'initialisation. Peut-être vous les calculez, et faites des mises à jour sélectives seulement des parties qui ont changé avant d'appeler invalidate() (par exemple les pixels de (0,0) - (10, l0) ont changé alors prenez le bitmap actuel et modifiez juste cette zone). Si le calcul des pixels est vraiment intrinsèquement lent, vous voudrez probablement créer un thread distinct pour faire cela (mettre à jour le bitmap avec les nouveaux pixels, puis postInvalidate() sur l'interface utilisateur pour les dessiner). De plus, maintenant que vous avez vos pixels dans un bitmap, vous pouvez faire des petits trucs comme réduire la taille de l'image bitmap et la mettre à l'échelle lorsque vous dessinez à l'écran, ce qui vous permet de mettre beaucoup moins de temps à interface utilisateur entière (quoique à une résolution inférieure).

+0

Merci, je suppose que tout cela est de bon sens.
Pour le moment, il faut environ 1 minute pour initialiser l'application avec le code dans ma routine OnDraw, tout ce qui est plus de 1 seconde est probablement inacceptable.
Cet appel peut initialiser mon bitmap avec la matrice de pixels dont j'ai besoin:
statique Bitmap CreateBitmap public (int [] couleurs, largeur int, int hauteur, config Bitmap.Config)
Il est vrai aussi que je vraiment pas besoin de résolution WVGA donc je vais expérimenter avec la mise à l'échelle.
Mattl

+0

J'ai passé la soirée à suivre ces conseils et j'ai obtenu mon rendu de près d'une minute à 3 secondes! Je pense que je peux raser une seconde de plus en optimisant davantage. Merci encore hackbod. – Mattl

+1

pouvez-vous montrer un exemple du code amélioré s'il vous plaît. –