android---surfaceview小结--(1)

在最近一个项目中需要在android端做曲线图并且高频刷新,所以来总结一下surfaceview的使用方法!
首先,项目要求是app通过网络接收数据,同时在屏幕上通过曲线图显示出来。数据更新的频率大约是每秒绘制120个点左右,而android系统设计的是绘图每秒刷新60次,那么每一次绘图大约绘制2个点,做出两段曲线
那么现在设想是两个线程,一个线程模拟从网络接收数据,一个线程用来绘图。那么步骤如下:
1. 继承surfaceview,实现SurfaceHolder.Callback接口:
public class TicSurfaceView extends SurfaceView implements SurfaceHolder.Callback
2. 重写如下方法,都是callback接口的:
(1)public abstract void surfaceChanged (SurfaceHolder holder, int format, int width, int height)
在这里设置对突发事件的处理。
(2)public abstract void surfaceCreated (SurfaceHolder holder)
在这里开启绘图线程。在本项目中开启socket线程用来接收数据。
(3)public abstract void surfaceDestroyed (SurfaceHolder holder)
用来终止绘图线程。
3. 部分代码分析
(1)
public void surfaceCreated(SurfaceHolder holder){
isNet = true; //线程开启,标志正在从网络上获取资源。
drawThead = new DrawThead(); //绘图线程
netThreadTest = new NetThreadTest(); //测试时模拟联网接受数据
drawThead.start();
netThreadTest.start();
}

在绘制过程中,安全的开启和终止一个线程最好是设置一个flag,线程开启时flag为true,在绘图的每一个循环当中检查flag,如果为false,那么就终止循环,终止线程。
(2)
public void surfaceDestroyed(SurfaceHolder holder) {
isNet = false;
drawThead = null;
netThreadTest = null;
//netThread = null;
}

在这里终止绘图以及网络线程。在此记录一下犯的一个错误:

public TicSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        initLinePaint();
        //错误:
        drawThead = new DrawThead();
        netThreadTest = new NetThreadTest();
    }
 public void surfaceCreated(SurfaceHolder holder){
        isNet = true; //线程开启,标志正在从网络上获取资源。
        drawThead.start();
        netThreadTest.start();
    }
public void surfaceDestroyed(SurfaceHolder holder) {
        isNet = false;
    }

在运行时,返回主屏幕,再返回应用,会:

java.lang.IllegalThreadStateException: Thread already started

此时,线程的run()方法已经运行完毕,activity中可能仍存在着该线程的实例对象,但是它已经不能再视为:独立可执行的了,线程的独立的call stack已经被dissolved,线程已经进行dead状态。不能再次start。
(3)

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        xOld = 0;
        yOld = ryCenter;
        Log.d(TAG_S,"Changed!!");
    }

在这里只需设置重新开始绘图即可。
(4)绘图线程:

class DrawThead extends Thread{
       @Override
       public void run() {
           super.run();
           ArrayList<int[]> drawbuf = new ArrayList<>(); //用来缓存数据
           boolean flag =true;
           while (isNet){ //当处于联网状态时
               synchronized (data){ //data是临界缓冲区
                   if (data.size() == 0){   
                       flag = false;
                   }else {
                       flag = true;
                       drawbuf = (ArrayList<int[]>)data.clone();//先取出数据,再绘制,避免网络线程等待
                       data.clear();//清空数据区
                   }
               }
               if (flag){
                   for (int i=0;i<drawbuf.size();i++){
                       int[] drawEachBuf = drawbuf.get(i);
                       simpleDraw(drawEachBuf);
                   }
               }

           }
       }
   }
private void simpleDraw(int[] dataone) {
        int xNew;
        int yNew;
        int yNew2;
        for (int i = 0; (i +1)< dataone.length && isNet; i=i+2) {
            if (xOld+2*defaultXoffset > mWidth){ //超出屏幕范围,重新绘制
                Canvas canvasT = surfaceHolder.lockCanvas(new Rect(xOld,0,mWidth,mHeight));
                canvasT.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);
                surfaceHolder.unlockCanvasAndPost(canvasT);
                xOld = 0;
                yOld = ryCenter;
            }
            xNew = xOld + 2*defaultXoffset;
            Canvas canvas = surfaceHolder.lockCanvas(new Rect(xOld, 0, xNew, mHeight));//在这里,锁定的canvas范围应当为绘图所需要的范围,不能太大,否则会因为刷新效率问题导致残影。
            canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);//清除画布
            yNew = ryCenter + dataone[i] * yScale;
            yNew2 = ryCenter + dataone[i+1]*yScale;
            canvas.drawLine(xOld, yOld, xNew-defaultXoffset, yNew, linePaint);
            canvas.drawLine(xNew-defaultXoffset,yNew,xNew,yNew2,linePaint);
            xOld = xNew;
            yOld = yNew2;
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }

绘图过程:首先获取Canvas,锁定,然后清除画布,画线,再提交释放。
再记录一下遇到的残影问题:设置绘图策略为:先清理整个屏幕,再绘制每一个点,绘完屏幕后再次清屏。这会导致在屏幕的左端出现范围不定的残影,但是如果自己手动测试会发现每一次的清屏仍然是有效的,即整个view被绘制为黑色,但是再次绘点描线时会出现残影,而且仍旧是在view的起始绘制处。
先写到这里,接下来的surfaceview的刷新频率,以及有关的paint和color相关的东西放到下一篇。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CruiseYoung提供的带有详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 该资料是《Android高级编程》的源代码 对应的书籍资料见: Android高级编程 基本信息 原书名: Professional Android Application Development 原出版社: Wrox 作者: (英)Reto Meier 译者: 王鹏杰 霍建同 出版社:清华大学出版社 ISBN:9787302228448 上架时间:2010-7-1 出版日期:2010 年6月 开本:16开 页码:398 版次:1-1 内容简介   android提供一个开放的开发环境,为针对移动设备编写创新应用程序带来了激动人心的新机遇。作为使用androidsdk构建这些应用程序的实用指南书籍,《android高级编程》从始至终穿插了一系列示例项目,每个项目都引入android的新功能和新技术,以助您达到最圆满的学习效果。书中介绍android的所有基本功能,并通过简明扼要的示例引导您使用高级功能。    《android高级编程》首先简要介绍android软件栈,接着陈述为手机创建稳定可靠、赏心悦目的应用程序的基本原理。通过学习,您可以打下牢固的理论根基,了解使用当前android 1.0 sdk编写定制移动程序所需的知识,还能灵活快捷地运用未来的增强功能构建最前沿的解决方案。    主要内容    ◆android移动开发的最佳实践    ◆简要介绍活动、intent、清单和资源    ◆如何使用布局和定制view创建用户界面    ◆存储和共享应用程序数据的技术    ◆如何创建基于地图的应用程序,如何使用gps和地理编码位置等基于位置的服务    ◆如何创建和使用后台服务及notification    ◆使用加速计、指南针和摄像头硬件    ◆与电话和网络硬件相关的所有内容,如电话api、sms和网络管理等    ◆高级开发主题,包括安全、ipc以及一些高级图形和用户界面技术    读者对象    本书面向希望在android手机平台上创建应用程序的所有人员。不管是经验丰富的移动开发人员,还是初出茅庐的新手,都能从本书提供的宝贵信息中获益。 作译者   Reto Meier出生于澳大利西南的珀斯市,现居伦敦。 Reto是一位经验丰富的软件开发人员,拥有逾10年的GUI程序架构、设计和开发经验。他在涉足IT行业前曾从事过海洋石油和天然气开发以及金融工作。 Reto始终不渝地追求掌握新技术,从2007年Android发布之初Reto就迷恋上了此项技术。他利用业余时间研究包括WPF在内的多种开发平台以及Google的各种开发工具。 详情请访问Reto的个人网站RadioactiveYak,网址是http://blog.radioactiveyak.com。 目录 封面 -14 封底 -13 扉页 -12 版权 -11 作者简介 -10 前言 -9 目录 -4 第1章 Android简介 1 1.1 一些背景信息 2 1.1.1 不远的过去 2 1.1.2 未来的前景 2 1.2 对Android的误解 3 1.3 开放的移动开发平台 3 1.4 自带的Android应用程序 4 1.5 Android SDK功能 5 1.5.1 对包括摄像头、GPS和加速计在内的硬件的访问 5 1.5.2 自带的Google地图、地理编码和基于位置的服务 6 1.5.3 后台服务 6 1.5.4 SQLite 数据存储和检索数据库 6 1.5.5 共享数据和应用程序间通信 7 1.5.6 使用Google Talk的P2P服务 7 1.5.7 扩展的数据支持和2D/3D图形 7 1.5.8 优化的内存和进程管理 8 1.6 开放手机联盟简介 8 1.7 运行Android的环境 8 1.8 从事Android开发的原因 9 1.8.1 推动Android普及的因素 9 1.8.2 Android的独到之处 10 1.8.3 改变移动开发格局 10 1.9 开发框架简介 11 1.9.1 开发包中的资源 11 1.9.2 理解Android软件栈 12 1.9.3 Dalvik虚拟机 13 1.9.4 Android应用程序架构 14 1.9.5 Android库 14 1.9.6 高级Android库 15 1.10 小结 16 第2章 开始入手 17 2.1 Android开发 18 2.1.1

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值