当前位置: 首页 > article >正文

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

目录

6、 设计一个GameLoop类别

7、 只诞生一次GameLoop对象​编辑


6、 设计一个GameLoop类别

  • 刚才的小线程,其实就扮演了游戏线程(Game thread)的角色,它负责控制游戏的循环。

// 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)。

 

// 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()函数。如下图:

// 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()函数。
    // 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线程所执行的。
     


http://www.kler.cn/a/471488.html

相关文章:

  • PostgreSQL学习笔记(二):PostgreSQL基本操作
  • asp.net core中的 Cookie 和 Session
  • 现代谱估计的原理及MATLAB仿真(二)(AR模型法、MVDR法、MUSIC法)
  • 搭建企业AI助理的创新应用与案例分析
  • 32单片机从入门到精通之数据处理——传感器接口(十二)
  • ros2-4.1 服务通信介绍
  • NVIDIA发布RTX 50系列显卡:性能飞跃,Blackwell架构引领新时代
  • Vue.js组件开发-实现图表数据动态展示
  • 继承(5)
  • Qt: 无法运行rc.exe
  • PyTorch 官方文档 中文版本
  • Axure PR 9 锚点定位滚动 设计交互
  • IP查询于访问控制保护你我安全
  • 虚拟机Linux Red Hat 7.9 Docker部署.Net 7 Zr.Admin项目(后端)
  • nfs开机自动挂载
  • 《Mcal》--MCU模块
  • HTML-多媒体标签
  • TypeScript语言的正则表达式
  • 区别:支持向量机 (SVM) 和逻辑回归
  • Flink概念知识讲解之:Restart重启策略配置
  • Python如何导入自定义的类
  • 12-Gin 中的 Session --[Gin 框架入门精讲与实战案例]
  • GDPU Android移动应用 期末习题集 一天速成(更新ing)
  • 如何确保爬虫程序稳定运行?
  • Baumer工业相机堡盟LXT工业相机如何升级固件使得相机具有RDMA功能
  • 数据治理如何激活企业沉睡数据价值?