Simple thread issue with Android animation

2019-02-18 08:51发布

问题:

I'm trying to implement a thread with some simple Android animation. I'm just getting an error with sleep() - It says I need a method for it. I know there is probably an obvious solution. My app just places a ball that moves in a circle at a random location. What I want is to continue placing shapes at random locations. Anyway, can someone please tell what I'm doing wrong with my thread? Thanks.

public class DrawingTheBall extends View {

Bitmap bball; 
Random randX, randY;
double theta;
Handler m_handler;
Runnable m_handlerTask;  //for some reason I get a syntax error here
m_handler = new Handler();

public DrawingTheBall(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
    bball = BitmapFactory.decodeResource(getResources(), R.drawable.blueball);  
    //randX = 1 + (int)(Math.random()*500); 
    //randY = 1 + (int)(Math.random()*500);
    randX = new Random();
    randY = new Random();
    theta = 45;
    new Thread(this).start();
}

public void onDraw(Canvas canvas){
    super.onDraw(canvas);
    //Radius, angle, and coordinates for circle motion  
    float a = 50;
    float b = 50;
    float r = 50;
    int x = 0;
    int y = 0;
    theta = theta + Math.toRadians(2);

    //move ball in circle
    if(x < canvas.getWidth()){
        x = randX.nextInt() + (int) (a +r*Math.cos(theta));
    }else{
        x = 0;
    }
    if(y < canvas.getHeight()){
        y = randY.nextInt() + (int) (b +r*Math.sin(theta));
    }else{
        y = 0;
    }
    Paint p = new Paint();

}

   m_handlerTask = new Runnable()
   {
     @Override 
     public void run() {

    // do something 
    m_handler.postDelayed(m_handlerTask, 1000); 
    invalidate();
     }
   };
   m_handlerTask.run();   

} }

回答1:

If you implement Thread or HandlerThread, be sure that your UI thread does not block while waiting for the worker thread to complete—do not call Thread.wait() or Thread.sleep().

http://developer.android.com/training/articles/perf-anr.html

Instead of blocking while waiting for a worker thread to complete, your main thread should provide a Handler for the other threads to post back to upon completion.

Using a Handler

   Handler m_handler;
   Runnable m_handlerTask ;  
   m_handler = new Handler();
   m_handlerTask = new Runnable()
   {
     @Override 
     public void run() {

    // do something 
    m_handler.postDelayed(m_handlerTask, 1000); // instad of 1000 mention the delay in milliseconds
     }
   };
   m_handlerTask.run(); 

When you require to cancel the handler use m_handler.removeCallbacks(m_handlerTask);

Example:

 public class MainActivity extends Activity {

RelativeLayout rl;
int x = 0,y=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    rl = (RelativeLayout) findViewById(R.id.rl);
    CustomView cv = new CustomView(this);
    rl.addView(cv);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public class CustomView extends View {

    Bitmap bball; 
    Random randX, randY;
    double theta;
    Handler m_handler;
    Paint p ;

    int width;
    int height;

    Runnable m_handlerTask;  


    public CustomView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        p= new Paint();
        bball = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);  
        //randX = 1 + (int)(Math.random()*500); 
        //randY = 1 + (int)(Math.random()*500);
        randX = new Random();
        randY = new Random();
        theta = 45;
        m_handler = new Handler();   
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        // TODO Auto-generated method stub
        super.onSizeChanged(w, h, oldw, oldh);
        width =w;
        height=h; 
    }

    public void move()
    {
        m_handlerTask = new Runnable()
           {
             @Override 
             public void run() {
                 //theta = theta + Math.toRadians(2);

                  if(x<300)
                   {
                       x= x+10;
                       invalidate();
                   }
          else if(x>300)
           {
               x=0;
               m_handler.removeCallbacks(m_handlerTask);

           }
          // canvas.drawBitmap(bball, x, y, p);
            m_handler.postDelayed(m_handlerTask, 3000); 

             }
           };
           m_handlerTask.run();  

    }

    public void onDraw(final Canvas canvas){
        super.onDraw(canvas);
       canvas.drawBitmap(bball, x, y, p);  
       if(x<300)
           {
           move();
           }
       else 
       {

           m_handler.removeCallbacks(m_handlerTask);

       }


    }


}
 }