why is my android application so slow?
android, java, lag, performance
Solution
The emulator is terribly slow and probably the cause of your issues. Nothing jumps out of your code, so try it on a real device before you tear your hair out trying to make it smoother.
Problem
I've been following this tutorial. I've been playing around with code, taking things out I don't need and adding things etc, but when I run it in the emulator the blocks move in a very stuttery motion. It's like I'm getting a low FPS. For the first second or so of running the application it runs smoothly and then again for about a second when I recompile it before it closes. Any idea how to make it run smoothly all the time? MainActivity.java ``` package com.example.mobilecoursework; import android.app.Activity; import android.os.Bundle; import android.view.Window; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(new Blocks(this)); } } ``` blocks.java ``` package com.example.mobilecoursework; import java.util.ArrayList; import java.util.Random; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.view.SurfaceHolder; import android.view.SurfaceView; class Blocks extends SurfaceView implements SurfaceHolder.Callback { // private BlockThread _thread; //declare an array of the block sprites private ArrayList<GraphicObject> _graphics = new ArrayList<GraphicObject>(); public Blocks(Context context) { super(context); getHolder().addCallback(this); _thread = new BlockThread(getHolder(), this); setFocusable(true); } public void DrawBlocks(){ for (int i=0; i < 20; i++) { //create new random x and y position values Random randX = new Random(); int i1=randX.nextInt(getWidth()-0) + 0; Random randY = new Random(); int i2=randY.nextInt(getHeight()-0) + 0; GraphicObject graphic = new GraphicObject(BitmapFactory.decodeResource(getResources(), R.drawable.block)); graphic.getCoordinates().setX((int) i1 - graphic.getGraphic().getWidth() / 2); graphic.getCoordinates().setY((int) i2 - graphic.getGraphic().getWidth() / 2); _graphics.add(graphic); } } public void updatePhysics() { GraphicObject.Coordinates coord; for (GraphicObject graphic : _graphics) { //move blocks down coord = graphic.getCoordinates(); coord.setY(coord.getY() + 5 ); // reset block if (coord.getY() + graphic.getGraphic().getHeight() > getHeight()+10) { coord.setY(-10); } } } @Override public void onDraw(Canvas canvas) { canvas.drawColor(Color.BLACK); Bitmap bitmap; GraphicObject.Coordinates coords; for (GraphicObject graphic : _graphics) { bitmap = graphic.getGraphic(); coords = graphic.getCoordinates(); canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder holder) { _thread.setRunning(true); _thread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // simply copied from sample application LunarLander: // we have to tell thread to shut down & wait for it to finish, or else // it might touch the Surface after we return and explode boolean retry = true; _thread.setRunning(false); while (retry) { try { _thread.join(); retry = false; } catch (InterruptedException e) { // we will try it again and again... } } } } class BlockThread extends Thread { private SurfaceHolder _surfaceHolder; private Blocks _Blocks; private boolean _run = false; public BlockThread(SurfaceHolder surfaceHolder, Blocks blocks) { _surfaceHolder = surfaceHolder; _Blocks = blocks; } public void setRunning(boolean run) { _run = run; } public SurfaceHolder getSurfaceHolder() { return _surfaceHolder; } @Override public void run() { Canvas c; _Blocks.DrawBlocks(); while (_run) { c = null; try { c = _surfaceHolder.lockCanvas(null); synchronized (_surfaceHolder) { _Blocks.updatePhysics(); _Blocks.onDraw(c); } } finally { // do this in a finally so that if an exception is thrown // during the above, we don't leave the Surface in an // inconsistent state if (c != null) { _surfaceHolder.unlockCanvasAndPost(c); } } } } } class GraphicObject { // // Contains the coordinates of the graphic. // public class Coordinates { private int _x = 100; private int _y = 0; public int getX() { return _x + _bitmap.getWidth() / 2; } public void setX(int value) { _x = value - _bitmap.getWidth() / 2; } public int getY() { return _y + _bitmap.getHeight() / 2; } public void setY(int value) { _y = value - _bitmap.getHeight() / 2; } public String toString() { return "Coordinates: (" + _x + "/" + _y + ")"; } } private Bitmap _bitmap; private Coordinates _coordinates; public GraphicObject(Bitmap bitmap) { _bitmap = bitmap; _coordinates = new Coordinates(); } public Bitmap getGraphic() { return _bitmap; } public Coordinates getCoordinates() { return _coordinates; } } ```