Android 如何正确恢复应用程序

Android 如何正确恢复应用程序,android,multithreading,surfaceview,Android,Multithreading,Surfaceview,我是Android和线程的新手 什么应用程序可以 我有一个简单的应用程序,它只显示一个位图在屏幕边界内反弹(即,如果位图击中屏幕的右边缘,它将反转方向) 问题 当我最小化应用程序时,它会冻结,有时加载需要很长时间,加载时我会看到一个黑屏 问题: 请尝试运行代码,它只是下面显示的一个文件,我只是使用SurfaceView作为布局。就应用程序的功能而言,没有什么先进之处。 我不明白为什么我们需要使用SurfaceHolder.Callback匿名类(在嵌套的SurfaceView类中的方法中使用),

我是Android和线程的新手

什么应用程序可以 我有一个简单的应用程序,它只显示一个位图在屏幕边界内反弹(即,如果位图击中屏幕的右边缘,它将反转方向)

问题 当我最小化应用程序时,它会冻结,有时加载需要很长时间,加载时我会看到一个黑屏

问题: 请尝试运行代码,它只是下面显示的一个文件,我只是使用SurfaceView作为布局。就应用程序的功能而言,没有什么先进之处。 我不明白为什么我们需要使用SurfaceHolder.Callback匿名类(在嵌套的SurfaceView类中的方法中使用),如果我编写的生命周期方法在嵌套的SurfaceView类中被主活动的onPause、onResume、onStop方法调用,则称为pause、resume和stop。整个代码显示在应用程序的结构之后,以查看我所做的概述,因为我没有看到SurfaceHolder.Callback方法的意义,所以我的意思是我不知道为什么我们需要使用surfaceCreated、surfaceChanged、surfaceDestroyed,我不知道在surfaceChanged中添加什么。我还有一个onSaveInstanceState和onRestoreInstance状态方法,它们只保存位图的x和y坐标

public class MainActivity extends Activity {

GameView gameView;
Handler myHandler;
int xPos = 0;
int yPos = 0;
int deltaX = 3;
int deltaY = 3;
int iconWidth;
int iconHeight;

static final String STATE_POS_X = "playerPosX";
static final String STATE_POS_Y = "playerPosY";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    myHandler = new Handler ();
    gameView = new GameView(this);
    setContentView(gameView);
}

class GameView extends SurfaceView {

    private SurfaceHolder surfaceHolder;
    private Bitmap bmpIcon;
    private MyThread myThread;

    volatile boolean playingGame = true;

    public GameView(Context context) {
        super(context);
        init();
    }

    public GameView(Context context,
                         AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public GameView(Context context,
                         AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init(){

        myThread = new MyThread(this);

        surfaceHolder = getHolder();
        bmpIcon = BitmapFactory.decodeResource(getResources(),
                R.drawable.rubberBall);

        iconWidth = bmpIcon.getWidth();
        iconHeight = bmpIcon.getHeight();

        surfaceHolder.addCallback( new SurfaceHolder.Callback(){

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                myThread.setRunning(true);
                myThread.start();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder,
                                       int format, int width, int height) {
                // What do I enter here???

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                boolean retry = true;
                myThread.setRunning(false);
                while (retry) {
                    try {
                        myThread.join();
                        retry = false;
                    } catch (InterruptedException e) {
                    }
                }
            }});
    }

    protected void drawSomething(Canvas canvas) {
        canvas.drawColor(Color.BLACK);
        canvas.drawBitmap(bmpIcon,
                getWidth()/2, getHeight()/2, null);

        xPos += deltaX;
        if(deltaX > 0){
            if(xPos >= getWidth() - iconWidth){
                deltaX *= -1;
            }
        }else{
            if(xPos <= 0){
                deltaX *= -1;
            }
        }

        yPos += deltaY;
        if(deltaY > 0){
            if(yPos >= getHeight() - iconHeight){
                deltaY *= -1;
            }
        }else{
            if(yPos <= 0){
                deltaY *= -1;
            }
        }

        canvas.drawColor(Color.BLACK);
        canvas.drawBitmap(bmpIcon,
                xPos, yPos, null);

    }

    public void pause() {
        playingGame = false;
        try {
            myThread.join();
        } catch (InterruptedException e) {
        }
    }

    public void resume() {
        playingGame = true;
        myThread = new MyThread(this);
        myThread.start();
    }

}//END INNER CLASS: GameView

class MyThread extends Thread {

    GameView myView;
    private boolean running = false;

    public MyThread(GameView view) {
        myView = view;
    }

    public void setRunning(boolean run) {
        running = run;
    }

    @Override
    public void run() {
        while (running){

            Canvas canvas = myView.getHolder().lockCanvas();

            if(canvas != null) {
                synchronized (myView.getHolder()) {
                    myView.drawSomething(canvas);
                }
                myView.getHolder().unlockCanvasAndPost(canvas);
            }

            try {
                this.sleep(30);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }//END WHILE
      }
}//END INNER CLASS: MyThread

/**
 * BELOW are Main Activity Life Cycle Call Back methods!
 *
 */
@Override
protected void onStop() {
    super.onStop();
    Log.d("onStop", "Main Activity's onStop called");
    while (true) {
        gameView.pause();
        break;
    }
    this.finish();
}

@Override
protected void onResume() {
    super.onResume();
    Log.d("onResume", "Main Activity's onResume called");
    gameView.resume();
}

@Override
protected void onPause() {
    super.onPause();
    Log.d("onPause", "Main Activity's onPause called");
    gameView.pause();
}

//save and restore state
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);

    // Save the user's current game state
    savedInstanceState.putInt(STATE_POS_X, xPos);
    savedInstanceState.putInt(STATE_POS_Y, yPos);
}

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    xPos = savedInstanceState.getInt(STATE_POS_X);
    yPos = savedInstanceState.getInt(STATE_POS_Y);
}

}//END CLASS: MainActivity

检查非常好的解释,因为SurfaceView对图形的控制更精细,不像使用自定义视图或使用预定义的图形输入或GUI元素绘制


请查看详细的说明,因为SurfaceView对图形的控制更为精细,不像使用自定义视图或使用预定义的图形输入或GUI元素绘制图形

MainActivity life cycle methods
--------------------------------
onCreate:
------------
-links up the layout which is the SurfaceView instance
-initialize variables

onPause:
---------
call the SurfaceView's custom pause method here in addition to calling the 
super's onPause

onStop:
------
call the SurfaceView's custom stop method here in addition to calling the 
super's onStop

onResume:
---------
call the SurfaceView's custom resume method here in addition to calling the 
super's onResume

  nested Thread class
  ------------------------
  run method to run SurfaceView

  nested class SurfaceView's life cycle methods
  -------------------------------------------------------
    pause method which pauses the worker thread 
    ---------------------------------------------
    stop the worker thread:

    stop method which stops the worker thread:
    -----------------------------------------
    stop the worker thread

    resume method which creates a new worker thread:
    ---------------------------------------------------
    make a new worker thread

    SurfaceHolder.Callback lifespan methods
    ***Why do we need to write the methods below if I have pause,
    resume stop already that will be called by the Main Activity's
    onXXX, respectively????
    ==========================================

    surfaceCreated:
    ---------------
    make a new worker thread

    surfaceChanged:
    ---------------
     What do I enter here??

    surfaceDestroyed:
    -----------------
    destroy current worker thread

    END of nested SurfaceView class

override onSaveInstanceState method:
------------------------------------
save the bitmap's position (x and y coordinates)

override onRestoreInstanceState method:
-----------------------------------------
restore the bitmap's position (x and y coordinates)

END of MainActivity