深入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号38 分钟前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号40 分钟前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best6 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk6 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭10 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
aqi0011 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体
androidwork13 小时前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
梦天201513 小时前
android核心技术摘要
android
szhangbiao15 小时前
“开发板”类APP如果做屏幕适配
android
高林雨露16 小时前
RecyclerView中跳转到最后一条item并确保它在可视区域内显示
android