2010-08-26 3 views
6

J'essaie de comprendre comment contourner mon problème. J'ai lu http://groups.google.com/group/android-developers/browse_thread/thread/a2aac88a08cb56c2/b7dff4ba388cd664?lnk=gst&q=SurfaceView#b7dff4ba388cd664 qui répond en quelque sorte à ma question mais pour autant que je sache, c'est une sorte de réponse "difficile". J'utilise SurfaceView de la manière habituelle (lock/unlockAndPost) pour dessiner un bitmap de mon arrière-plan quand la surface est changée (ex: orientation, etc.) et je suis en train de rendre une série de mouvements cercles (jusqu'à 30 avec un rayon d'environ 25.f). Les données x, y pour les positions de ces cercles proviennent d'un serveur et tout va bien. Tous les objets de cercle sont stockés dans une liste et leur position est mise à jour en veillant à ce que cette mise à jour soit synchronisée. Cependant, lorsque je dessine ces cercles à l'écran (pendant canvas.lock()), la plupart du temps ils sont bien rendus mais parfois (par exemple toutes les quelques secondes) certains cercles semblent se déchirer ou scintiller brièvement pour un cadre. Le nombre de cercles est toujours constant donc ce n'est pas le problème et il n'y a pas de modifications simultanées à la liste des cercles (comme je l'ai dit, il est synchronisé). J'ai même essayé de dessiner tous ces cercles sur une image bitmap sur chaque boucle de rendu et de dessiner cette image dans le canevas principal. Cela semble juste affecter la performance encore plus (~ 13FPS par opposition à ~ 30FPS lors du dessin des cercles directement sur la toile principale). Désolé si l'information est un peu vague les gars, (en essayant de garder l'entreprise heureuse: p) mais je me demandais si quelqu'un pouvait me donner un indice? Ou suis-je juste pas de chance. Je devrais noter que les données de positionnement provenant du serveur sont des données en temps réel et il est d'une importance vitale que le rendu reflète ces positions en temps réel.SurfaceView scintillement/déchirement

Merci pour toute aide! Chris

EDIT:

assez juste. Voici le run() du thread de rendu.

@Override 
    public void run() { 
     Canvas c; 
     while (mRun) { 
      c = null; 
      try { 
       c = mSurfaceHolder.lockCanvas(null); 
       synchronized (mSurfaceHolder) { 
        panel.onDraw(c); 
       } 
      } finally { 
       if (c != null) { 
        mSurfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 

plutôt standard (presque une copie carbone du module lunaire: p)

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    mBackground= Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.RGB_565); 
    screenOrientation = getResources().getConfiguration().orientation; 
    if(thread.getState()== Thread.State.TERMINATED){ 
     thread = new RenderThread(holder, this); 
     thread.setRunning(true); 
     thread.start(); 
    }else { 
     thread.setRunning(true); 
     thread.start(); 
    } 
} 



@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
    Canvas c = new Canvas(mField); 
    c.drawARGB(255,0,144,0); 
    backgroundDetails.renderOnPanel(c, this); 
    screenOrientation = getResources().getConfiguration().orientation; 
} 

assez facile à suivre, redessiner tout le bitmap d'arrière-plan si les changements d'orientation et de commencer le fil de rendu.

public void onDraw(Canvas canvas) { 
    canvas.drawBitmap(mField,0,0,null); 
    drawPositionBeans(canvas, this); 
} 

Et enfin:

public void onDraw(Canvas canvas, RadarView radarView) { 
    float beanX=0, beanY=0; 
    float radius = 25.0f; 
    final List<PositionBean> copyOfList = Collections.synchronizedList(positionBeans.getPositionBeans()); 
    synchronized(copyOfList){ 
     try { 
      for (final PositionBean pb : copyOfList) 
      { 
       if (panel.getOrientation() == Configuration.ORIENTATION_PORTRAIT) { 
        beanX = (float)pb.getY()*(-1); 
        beanY = (float)pb.getX(); 
       } else { 
        beanX = (float)pb.getY()*(-1); 
        beanY = (float)pb.getX()*(-1); 
       } 
       mPaint.setARGB(255,pb.getRgbColor().getR(), pb.getRgbColor().getG(), pb.getRgbColor().getB()); 
       panel.drawSpot(canvas, beanX, beanY, radius, mPaint); 

       mPaint.setStyle(Paint.Style.STROKE); 
       mPaint.setARGB(255,255,222,1); 
       for (int j = 0; j < selectedBean.size(); ++j) 
       { 
        if(pb.getTrack()==selectedBean.get(j)) { 
         panel.drawSpot(canvas, beanX, beanY, radius+1, mPaint); 
        } 
       } 
       mPaint.setStyle(Paint.Style.FILL); 
      } 

     } catch(Exception e) { 
      Log.e("render", "Exception Drawing Beans: " + e); 
     } 
    } 
} 

Merci encore les gars. Chris

+0

Impossible de répondre sans voir votre gameloop et code de dessin. – Sebi

+0

Comme Sebi l'a dit - un exemple de code serait utile - mais avez-vous considéré la possibilité que les positions que vous recevez à l'occasion soient incorrectes? Juste une réflexion sur la raison pour laquelle les cercles pourraient «scintiller», s'ils sont positionnés hors vue temporairement. Encore une fois, sans aucun code, il sera impossible de répondre. – Seidr

+0

Un grand merci pour l'aide les gars. Mais oui je suis sûr que les données de positionnement sont correctes. –

Répondre

0

J'ai eu ce problème. La solution qui me convient est la synchronisation de la méthode et de la méthode onDraw qui met à jour la matrice de transformation. Parce qu'il y avait des cadres lorsque la matrice est identique (valeur initiale de la nouvelle matrice()) et dans la trame suivante, elle avait de bonnes valeurs.

0

Je trouve après avoir lu un peu de vue sur la surface que si vous appelez

getHolder().lockCanvas(); 

Vous devez dessiner tout encore.

Sauf si vous fournissez votre zone sale.

getHolder().lockCanvas(Rect dirty); 

Si vous voulez seulement redessiner la zone définie par la Rect

Questions connexes