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

ops/2025/1/12 9:55:22/

目录

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.ppmy.cn/ops/149414.html

相关文章

观察者模式详解

观察者模式详解 1. 定义与描述 观察者模式是一种行为型设计模式&#xff0c;它定义了对象之间的一种一对多依赖关系。这种模式中&#xff0c;有一个被观察的对象&#xff08;称为主题Subject&#xff09;和多个观察该对象的观察者&#xff08;Observer&#xff09;。主题对象负…

概率论与数理统计总复习

复习课本&#xff1a;中科大使用的教辅《概率论和数理统计》缪柏其、张伟平版本 目录 0.部分积分公式 1.容斥原理 2.条件概率 3.全概率公式 4.贝叶斯公式 5.独立性 6.伯努利分布&#xff08;两点分布&#xff09; 7.二项分布 8.帕斯卡分布&#xff08;负二项分布&am…

【计算机网络】第六章·应用层

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;计算机网络_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2…

PPT素材免费下载

下载免费的PPT模板、素材、背景、图表、课件等等就上这6个网站&#xff0c;赶紧收藏&#xff01; 1、菜鸟图库 ppt模板免费下载|ppt背景图片 - 菜鸟图库 菜鸟图库网有非常丰富的免费素材&#xff0c;像设计类、办公类、自媒体类等素材都很丰富。PPT模板种类很多&#xff0c;全…

Mysql连接报错排查解决记录

Mysql连接报错排查解决记录 背景&#xff1a; 系统&#xff1a;uos server-1060e​ 运行环境kvm虚拟机​ mysql版本&#xff1a;5.7.44, for Linux (x86_64)问题现象&#xff1a; 宿主机重启后&#xff0c;kvm虚拟机内的mysql服务无法远程连接了。通过不同的客户端工具连接…

PHP获取局域网ip(192.168)

有时候&#xff0c;程序中&#xff0c;需要获取本机内网ip的情况&#xff0c;经过各种资料查找&#xff0c;最终确定一下代码&#xff1a; //获取内网ipfunction getLocalIP() {exec("ipconfig /all",$arr);$res mb_convert_encoding($arr, UTF-8, GBK);$ip ;fore…

python 个人学习笔记

个人学习笔记 关键字 if __name__ __main__ if __name__ __main__: 是 Python 中一个常用的代码结构&#xff0c;它的作用是判断当前脚本是否作为主程序直接运行&#xff0c;还是被作为模块导入到其他脚本中使用。 以下详细解释&#xff1a; __name__ 是 Python 中的一个内置…

深入NLP核心技术:文本张量表示与词嵌入全面解析

系列文章目录 01-中文NLP入门必备&#xff1a;全面解析分词、命名实体识别与词性标注&#xff08;附详细实战案例&#xff09; 02-深入NLP核心技术&#xff1a;文本张量表示与词嵌入全面解析 文章目录 系列文章目录前言一、文本张量表示1.1 文本张量表示简介1.1.1 举例说明1.1…