深入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线程所执行的。

相关推荐
xvch16 分钟前
Kotlin 2.1.0 入门教程(二十五)类型擦除
android·kotlin
simplepeng9 小时前
我的天,我真是和androidx的字体加载杠上了
android
小猫猫猫◍˃ᵕ˂◍10 小时前
备忘录模式:快速恢复原始数据
android·java·备忘录模式
CYRUS_STUDIO12 小时前
使用 AndroidNativeEmu 调用 JNI 函数
android·逆向·汇编语言
梦否12 小时前
【Android】类加载器&热修复-随记
android
徒步青云12 小时前
Java内存模型
android
今阳13 小时前
鸿蒙开发笔记-6-装饰器之@Require装饰器,@Reusable装饰器
android·app·harmonyos
-优势在我17 小时前
Android TabLayout 实现随意控制item之间的间距
android·java·ui
hedalei17 小时前
android13修改系统Launcher不跟随重力感应旋转
android·launcher
Indoraptor19 小时前
Android Fence 同步框架
android