使用线程在Android中移动多个位图

时间:2014-05-21 15:00:56

标签: android multithreading bitmap

在我的第一个Android应用程序中,我的线程有问题。事实上,当我触摸屏幕时,我希望它像我想要的那样发射许多恒星(射弹)。但是目前,经过一次触摸,我收到一条消息,告诉我应用程序'没有响应......

我找不到解决方案。

这是我的代码:(注意:法语中有评论,只是忽略它)

package com.example.slider;

import java.util.Stack;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;

public class TirMissile extends Activity implements OnTouchListener {

BringBackSurface aBackSurface;
float x, y, sX, sY, fX, fY; // s=Starting f=Final
int i;
Bitmap test, test1;
ThreadProjectile aTP;
Stack<Projectile> aProjectileAttente;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    aBackSurface = new BringBackSurface(this);
    aBackSurface.setOnTouchListener(this);

    x = 0; y = 0; sX = 0; sY = 0; fX = 0; fY = 0;   
    i=0;

    test = BitmapFactory.decodeResource(getResources(), android.R.drawable.btn_star_big_on);
    test1 = BitmapFactory.decodeResource(getResources(), android.R.drawable.btn_star_big_off);

    //full screen
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(aBackSurface);


    Log.d("TEST","test01"); 

}

@Override
protected void onPause() {
    super.onPause();
    aBackSurface.pause();
}

@Override
protected void onResume() {
    super.onResume();       
    aBackSurface.resume();
    Log.d("TEST","test0");
    aBackSurface.getHolder().addCallback(new MyCallback());

}

@Override
public boolean onTouch(View v, MotionEvent event) { // event = down/up/right/release/value/etc...
    try {
        Thread.sleep(50);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    x = event.getX(); 
    y = event.getY(); 

    switch(event.getAction()) { 

    case MotionEvent.ACTION_UP:
        fX = event.getX();
        fY = event.getY();

        Projectile vProjectile = new Projectile(50,50,fX,fY,50,test);

        if(i==0){
            this.aProjectileAttente = new Stack<Projectile>();
        }

        this.aProjectileAttente.push(vProjectile);

        if(i==0){
            this.aTP.setStack(this.aProjectileAttente);
            aBackSurface.resume();
            aTP.run();
            i++;
        }           

        Log.d("TEST","test10");

    }

    return true; // si true, x et y seront constament mesurés tant qu'on maintient le doight sur l'écran
}


public class MyCallback implements SurfaceHolder.Callback {
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){
        Canvas canvas= holder.lockCanvas();
        canvas.drawRGB(02, 02, 150);
        holder.unlockCanvasAndPost(canvas); 
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Canvas canvas= holder.lockCanvas();
        canvas.drawRGB(02, 02, 150);
        holder.unlockCanvasAndPost(canvas);         
        aTP = new ThreadProjectile(aBackSurface);
        Log.d("TEST","test110");            
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }
}
  }

第二课:

  package com.example.slider;

  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.Stack;
  import android.graphics.Canvas;
  import android.util.Log;
  import com.example.slider.BringBackSurface;

  public class ThreadProjectile implements Runnable{


private ArrayList<Projectile> aALprojectile;
private BringBackSurface aBBS;
private Stack<Projectile> aProjectileAttente;


public ThreadProjectile( final BringBackSurface BBS) {

    this.aBBS = BBS;
    this.aALprojectile = new ArrayList<Projectile>();
    Log.d("TEST","test2");

}

public void setStack(Stack<Projectile> stack){
    this.aProjectileAttente = stack;
}

private void updateProjectile() {
    Log.d("UPDATE", "update en cours");
    while( !this.aProjectileAttente.isEmpty() )
        aALprojectile.add( this.aProjectileAttente.pop() );
}

@Override
public void run() {

    Projectile vProjectile;
    float nX, nY;
    Canvas canvas = null; 
    Iterator<Projectile> vIt;

    while(aBBS.getRunning()) {  

        updateProjectile();
        vIt = aALprojectile.iterator();
        if( !this.aBBS.getHolder().getSurface().isValid() ) continue; // si ce n'est pas valide, on continue (continue fonctionne comme un statut break et nous )           
        canvas= this.aBBS.getHolder().lockCanvas();
        if(canvas == null) Log.e("CANVAS", "Pas de Canvas");            
        canvas.drawRGB(02, 02, 150); // coloriage du background     
        Log.d("BACKGROUND","test205");

        while(vIt.hasNext()) {

            vProjectile = vIt.next();
            nX = vProjectile.getX() + vProjectile.getVX();
            nY = vProjectile.getY() + vProjectile.getVY();


            if(nX < 0 || nY < 0 || nX > aBBS.getWidth() || nY > aBBS.getHeight() ) vIt.remove();
            else{
                canvas.drawBitmap(vProjectile.getBitmap(), nX-(vProjectile.getBitmap().getWidth()/2) , nY-(vProjectile.getBitmap().getHeight()/2), null);
                vProjectile.setX(nX);
                vProjectile.setY(nY);
            }                           
            Log.d("TEST","X:"+nX+" Y:"+nY);                 
        }
        Log.d("TEST","test207");
        this.aBBS.getHolder().unlockCanvasAndPost(canvas);                  
    }   

}

 }

上课使用:

 package com.example.slider;

 import android.content.Context;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;

 public class BringBackSurface extends SurfaceView { // Cette classe dans cette classe pour avoir accès aux valeurs de X et Y  (XML?) dans la méthode onTouch() 

public SurfaceHolder aHolder;

public boolean aIsRunning = false; // notre thread va aller dans le onresume() donc va passer en true

public BringBackSurface(Context context) {
    super(context);
}

public void pause(){
    aIsRunning = false;
}

public void resume(){
    aHolder = getHolder();
    aIsRunning = true;
}

public boolean getRunning() {
    return aIsRunning;
}

 }

谢谢。

1 个答案:

答案 0 :(得分:0)

我会说你需要分开你的代码;在OnTouch函数上我不会实际绘制,只是用它来计算坐标(正如你所做的那样)并调用另一个类绘制。

我不久前就提出了关于画布的问题,我认为你会发现它足智多谋(我希望如此):Drawing fast in canvas Bitmap android ics

正如你所看到的,我创建了一个自定义类来绘制:

private class Painter extends View{
public Painter(Context context){
    super(context);
}

public void draw() {
    //more code on the source
}

在onTouch事件中,我尽量做到最小,因为我遇到了和你一样的问题。

希望它有所帮助。