深入Android架构(从线程到AIDL)_16 应用Android的UI框架03

目录

[6、 设计一个GameLoop类别](#6、 设计一个GameLoop类别)

[7、 只诞生一次GameLoop对象​编辑](#7、 只诞生一次GameLoop对象编辑)


6、 设计一个GameLoop类别

  • 刚才的小线程,其实就扮演了游戏线程(Game thread)的角色,它负责控制游戏的循环。
java 复制代码
// myView.java
//......
public class myView extends View {
    //..........
    @Override 
    protected void onDraw(Canvas canvas) {
        //..............
        myThread t = new myThread();
        t.start();
    }

    class myThread extends Thread{
        public void run() {
            postInvalidateDelayed(1000);
        }
    };
}
  • 于是,我们将刚才的小线程部分独立出来,成为一个独立的类别,通称为游戏线程(Game Thread) 或游戏循环(Game Loop)。
java 复制代码
// GameLoop.java
// .........
public class GameLoop extends Thread {
    myView mView;
    GameLoop(myView v){
        mView = v;
    }

    public void run() {
        mView.onUpdate();
        mView.postInvalidateDelayed(1000);
    }
}

// myView.java
// ...........
public class myView extends View {
    private Paint paint= new Paint();
    private int x, y;
    private int line_x = 100;
    private int line_y = 100;
    private float count = 0;
    myView(Context ctx) {
        super(ctx);
    }

    public void onUpdate(){
        if( count > 12) count = 0;
        x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));
        y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));
        count++;
    }

    @Override 
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(3);
        canvas.drawLine(line_x, line_y, line_x+x, line_y+y, paint);
        paint.setStrokeWidth(2);
        paint.setColor(Color.RED);
        canvas.drawRect(line_x-5, line_y - 5, line_x+5, line_y + 5, paint);
        paint.setColor(Color.CYAN);
        canvas.drawRect(line_x-3, line_y - 3, line_x+3, line_y + 3, paint);
        //--------------------------------
        GameLoop loop = new GameLoop(this);;
        loop.start();
    }
}
  • 首先由myActivity来诞生myView对象,然后由Android框架調用myView的onDraw()函数来绘图和显示。绘图完毕,立即诞生一个GameLoop对象,并調用start()函数去启动一个小线程去調用postInvalidate()函数。就触发UI线程重新調用myView的onDraw()函数。

7、 只诞生一次GameLoop对象

  • 每次执行onDraw()时,都会重新诞生一次GameThread对象,也诞生一次游戏线程去調用postInvalidate()函数。似乎是UI线程控制着游戏线程,这样游戏线程就不能扮演主控者的角色了。
  • 于是,可换一个方式:一开始先诞生一个游戏线程,并且使用while(true)来创造一个无限循环(Endless Loop),让游戏线程持续绕回圈,而不会停止。
  • 在诞生myView时,就诞生GameLoop对象,且調用其start()函数来启动游戏线程。此时游戏线程处于<暂停>状态,虽然继续绕回圈,但是并不会調用postInvalidate()函数。接着,由Android框架調用myView的onDraw()函数来绘图和显示。
  • 绘图完毕,立即調用GameLoop的loopResume()函数,让GameLoop从<暂停>状态转移到<执行>状态。此时,这游戏线程就去調用postInvalidate()函数,触发UI线程重新調用myView的onDraw()函数。如下图:
java 复制代码
// GameLoop.java
// ........
public class GameLoop extends Thread {
    private myView mView;
    private boolean bRunning;
    GameLoop(myView v){
        mView = v; bRunning = false; }

    public void run() {
        while(true){
            if(bRunning){
                mView.onUpdate();
                mView.postInvalidateDelayed(1000);
                loopPause();
            } 
        }
    }
    public void loopPause(){ bRunning = false; }
    public void loopResme(){ bRunning = true; }
}
  • 其中, loopPause()函数将bRunning设定为false,游戏线程就处于<暂停>状态。loopResume()函数将bRunning设定为true,游戏线程就处于<执行>状态,就会調用myView的onUpdate()函数,去更新绘图的设定。

  • 然后調用postInvalidate()函数,触发UI线程去重新調用onDraw()函数。

    java 复制代码
    // myView.java
    // .........
    public class myView extends View {
        private Paint paint= new Paint();
        private int x, y;
        private int line_x = 100, line_y = 100;
        private float count;
        private GameLoop loop;
    
        myView(Context ctx) {
            super(ctx);
            init();
            loop = new GameLoop(this);
            loop.start();
        }
    
        public void init(){
            count = 0;
            x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));
            y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));
        }
    
        public void onUpdate(){ // 游戏线程执行的
            if( count > 12) count = 0;
            x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));
            y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));
            count++;
        }
    
        @Override 
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawColor(Color.WHITE);
            paint.setColor(Color.BLUE);
            paint.setStrokeWidth(3);
            canvas.drawLine(line_x, line_y, line_x+x, line_y+y, paint);
            paint.setStrokeWidth(2);
            paint.setColor(Color.RED);
            canvas.drawRect(line_x-5, line_y - 5, line_x+5,
            line_y + 5, paint);
            paint.setColor(Color.CYAN);
            canvas.drawRect(line_x-3, line_y - 3, line_x+3,line_y + 3, paint);
            //--------------------------------
            loop.loopResme();
        }
    }

    • 请留意: onUpdate()函数是由游戏线程所执行的;而onDraw()则是由UI线程所执行的。

相关推荐
命运之手1 小时前
[ Android ] Query If Package is Installed
android·packagemanager·installed
唔661 小时前
Android 系统签名 keytool-importkeypair
android
练小杰1 小时前
Linux 文件的特殊权限—ACL项目练习
android·linux·运维·服务器·经验分享·学习
摇光932 小时前
js适配器模式
android·okhttp·适配器模式
xChive2 小时前
解决 uniapp 开发中的相机相册权限申请同步告知目的问题(兼容 Android 13)| 华为应用商店上架解决方案
android·uni-app·vue
susu10830189113 小时前
android studio使用Material Design中的ToolBar
android·ide·android studio
SoulKuyan3 小时前
Android客制化------7.0设置壁纸存在的一些问题
android·开发语言·python
timer_0173 小时前
Swoole v6 正式发布
android
lph0093 小时前
android compose 串口通信
android
Hacker_xingchen4 小时前
CTF知识点总结(一)
android