当前位置:  移动开发 iis7站长之家
本页文章导读:
    ▪SurfaceView传记        SurfaceView杂记 使用的SurfaceView的时候,一般情况下还要对其进行创建,销毁,改变时的情况进行监视,这就要用到SurfaceHolder.Callback.   只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实.........
    ▪ schedule跟scheduleAtFixedRate的区别        schedule和scheduleAtFixedRate的区别 Java代码   import java.util.Timer;   import java.util.TimerTask;   import java.util.Date;      /**   * @author vincent   */   public class TimerTest {       public static.........
    ▪ 玩转Andorid-组件篇-Service(服务)之RPC远程进程调用       玩转Andorid---组件篇---Service(服务)之RPC远程进程调用   在Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进程之.........

[1]SurfaceView传记
    来源: 互联网  发布时间: 2014-02-18
SurfaceView杂记

使用的SurfaceView的时候,一般情况下还要对其进行创建,销毁,改变时的情况进行监视,这就要用到SurfaceHolder.Callback.

 

只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口:
 surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。 
 surfaceChanged(SurfaceHolder holder, int format, int width,int height):当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。 
 surfaceDestroyed(SurfaceHolder holder):当Surface被摧毁前会调用该函数,该函数被调用后就不能继续使用Surface了,一般在该函数中来清理使用的资源。 
 
通过SurfaceView的getHolder()函数可以获取SurfaceHolder对象,Surface 就在SurfaceHolder对象内。虽然Surface保存了当前窗口的像素数据,但是在使用过程中是不直接和Surface打交道的,由SurfaceHolder的Canvas lockCanvas()或则Canvas lockCanvas(Rect dirty)函数来获取Canvas对象,通过在Canvas上绘制内容来修改Surface中的数据。如果Surface不可编辑或则尚未创建调用该函数会返回null,在 unlockCanvas() 和 lockCanvas()中Surface的内容是不缓存的,所以需要完全重绘Surface的内容,为了提高效率只重绘变化的部分则可以调用lockCanvas(Rect dirty)函数来指定一个dirty区域,这样该区域外的内容会缓存起来。在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、修改)。
当在Canvas中绘制完成后,调用函数unlockCanvasAndPost(Canvas canvas)来通知系统Surface已经绘制完成,这样系统会把绘制完的内容显示出来。为了充分利用不同平台的资源,发挥平台的最优效果可以通过SurfaceHolder的setType函数来设置绘制的类型,目前接收如下的参数:
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface 
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface 
SURFACE_TYPE_GPU:适用于GPU加速的Surface 
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。 

 

访问SurfaceView的底层图形是通过SurfaceHolder接口来实现的,通过getHolder()方法可以得到这个SurfaceHolder对象。你应该实现surfaceCreated(SurfaceHolder)和surfaceDestroyed(SurfaceHolder)方法来知道在这个Surface在窗口的显示和隐藏过程中是什么时候创建和销毁的。

 

注意:一个SurfaceView只在SurfaceHolder.Callback.surfaceCreated() 和 SurfaceHolder.Callback.surfaceDestroyed()调用之间是可用的,其他时间是得不到它的Canvas对象的(null)。

 

 

附:SurfaceView和View最本质的区别

SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。
那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。
当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。

所以基于以上,根据游戏特点,一般分成两类。

1 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

2 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。


    
[2] schedule跟scheduleAtFixedRate的区别
    来源: 互联网  发布时间: 2014-02-18
schedule和scheduleAtFixedRate的区别


Java代码  
  • import java.util.Timer;  
  • import java.util.TimerTask;  
  • import java.util.Date;  
  •   
  • /** 
  •  * @author vincent 
  •  */  
  • public class TimerTest {  
  •   
  •  public static void main(String[] args) {  
  •   Timer t = new Timer();  
  •     
  •   //在5秒之后执行TimerTask的任务  
  •   t.schedule(new TimerTask(){  
  •      public void run()  
  •      {System.out.println("this is task you do1");}  
  •     },5*1000);  
  •   
  •   
  •   //在Date指定的特定时刻之后执行TimerTask的任务  
  •   Date d1 = new Date(System.currentTimeMillis()+1000);  
  •   t.schedule(new TimerTask(){  
  •    public void run()  
  •    {System.out.println("this is task you do2");}  
  •   },d1);  
  •   
  •   
  •   //在Date指定的特定时刻之后,每隔1秒执行TimerTask的任务一次  
  •   Date d2 = new Date(System.currentTimeMillis()+1000);  
  •   t.schedule(new TimerTask(){  
  •    public void run()  
  •    {System.out.println("this is task you do3");}  
  •   },d2,1*1000);  
  •   
  •   
  •   //在3秒之后,每隔1秒执行TimerTask的任务一次  
  •   t.schedule(new TimerTask(){  
  •    public void run()  
  •    {System.out.println("this is task you do4");}  
  •   },3*1000,1*1000);  
  •     
  •   //在3秒之后,绝对每隔2秒执行TimerTask的任务一次  
  •   
  •   t.scheduleAtFixedRate(new TimerTask(){  
  •    public void run()  
  •    {System.out.println("this is task you do6");}  
  •   },3*1000,2*1000);  
  •  }  
  •  

    schedule和scheduleAtFixedRate的区别在于,如果指定开始执行的时间在当前系统运行时间之前,scheduleAtFixedRate会把已经过去的时间也作为周期执行,而schedule不会把过去的时间算上。

    比如

    Java代码  
  • SimpleDateFormat fTime = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");  
  •   Date d1 = fTime.parse("2005/12/30 14:10:00");  
  •     
  •   t.scheduleAtFixedRate(new TimerTask(){  
  •    public void run()  
  •    {  
  •        System.out.println("this is task you do6");  
  •    }  
  •   },d1,3*60*1000);  
  •  

    间隔时间是3分钟,指定开始时间是2005/12/30 14:10:00,如果我在14:17:00分执行这个程序,那么会立刻打印3次

    this is task you do6     //14:10
    this is task you do6     //14:13
    this is task you do6     //14:16

    并且注意,下一次执行是在14:19 而不是 14:20。就是说是从指定的开始时间开始计时,而不是从执行时间开始计时。

    但是上面如果用schedule方法,间隔时间是3分钟,指定开始时间是2005/12/30 14:10:00,那么在14:17:00分执行这个程序,则立即执行程序一次。并且下一次的执行时间是 14:20,而不是从14:10开始算的周期(14:19)。


        
    [3] 玩转Andorid-组件篇-Service(服务)之RPC远程进程调用
        来源: 互联网  发布时间: 2014-02-18
    玩转Andorid---组件篇---Service(服务)之RPC远程进程调用

     

    在Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进程之间相互通信。为了实现进程之间的相互通信,Andorid采用了一种轻量级的实现方式RPC(Remote Procedure Call 远程进程调用)来完成进程之间的通信,并且Android通过接口定义语言(Andorid Interface Definition Language ,AIDL)来生成两个进程之间相互访问的代码,例如,你在Activity里的代码需要访问Service中的一个方法,那么就可以通过这种方式来实现了。

    AIDL RPC机制是通过接口来实现的,类似Windows中的COM或者Corba,但他是轻量级的,客户端和被调用实现之间是通过代理模式实现的,代理类和被代理类实现同一个接口Ibinder接口。

     

    实例练习:

    <!--[if !supportLists]-->1、  <!--[endif]-->创建一个项目,在包中创建一个AIDL文件,定义一个AIDL文件的语法和定义一个JAVA接口的语法类似,只不过文件的扩展名是“.aidl”。在AIDL文件中可以声明任一多个方法,方法可以带参数,也可以有返回值,参数和返回值是任意类型。需要注意的是,你必须导入除了内建类型(例如:int,boolean等)外的任何其他类型,即使他们在同一个包中,具体规则如下:

    <!--[if !supportLists]-->①     <!--[endif]-->JAVA原始类型不需要导入

    <!--[if !supportLists]-->②     <!--[endif]-->String,List,Map和CharSequence不需要导入

    定义好的 AIDL文件可以使用ADT插件自动生成java代码

     

    现在开始写代码:

    创建一个名字为IPerson.aidl的文件

     

    package org.hualang.rpc;
    
    //IPerson接口
    interface IPerson
    {
    	//设置年龄
    	void setAge(int age);
    	//设置姓名方法
    	void setName(String name);
    	//显示信息方法
    	String display();
    }

     2、当创建好这个文件后,刷新工程,就会在gen目录下看到这个java接口



     当你分析了这个代码后会发现,它是使用的代理模式来实现的,我们一般定义该接口的静态内部类Stub的asInterface()方法,返回我们的接口

    3、实现AIDL文件生成的JAVA接口

    AIDL会生成一个和.aidl文件同名的JAVA接口文件,该接口中有一个静态抽象内部类Stub,该类中声明了AIDL文件中定义的所有方法,其中有一个重要的方法是asInterface(),该方法通过代理模式返回JAVA接口的实现

    我们可以定义一个实现类,PerionImpl,该类继承Stub类,实现我们定义的3个方法

    /**
     * @author hualang
     * IPerson接口实现类
     */
    package org.hualang.rpc;
    
    import android.os.RemoteException;
    
    public class IPersonImpl extends IPerson.Stub {
    	//声明两个变量
    	private int age;
    	private String name;
    	//显示name和age
    	public String display() throws RemoteException
    	{
    		return "name="+name+";age="+age;
    	}
    	@Override
    	public void setAge(int age) throws RemoteException {
    		// TODO Auto-generated method stub
    		this.age = age;
    	}
    
    	@Override
    	public void setName(String name) throws RemoteException {
    		// TODO Auto-generated method stub
    		this.name = name;
    	}
    	
    }
    

     4、将你的接口暴露给客户端

    现在我们已经实现了IPerson接口,接下俩我们要看看如何将该接口暴露给客户端调用。一般我们通过定义一个Service来实现,在Service的onBind()方法中返回该接口,当我们板顶该接口时调用该方法。

    /**
     * @author hualang
     * 使用Service将接口暴露给客户端
     */
    package org.hualang.rpc;
    
    import org.hualang.rpc.IPerson.Stub;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    
    public class RemoteService extends Service {
    	//声明IPerson接口
    	private Stub iperson = new IPersonImpl();
    	public IBinder onBind(Intent intent)
    	{
    		return iperson;
    	}
    }

     5、客户端调用

    接下来定义一个Activity来绑定远程Service,获得IPerson接口,通过RPC机制调用接口中的方法。

    /**
     * @author hualang
     * IPerson接口实现类
     */
    package org.hualang.rpc;
    
    import android.app.Activity;
    import android.app.Service;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.Toast;
    
    public class RPCTest extends Activity {
        /** Called when the activity is first created. */
    	private IPerson iPerson;
    	private Button btn;
    	private ServiceConnection conn = new ServiceConnection()
    	{
    		synchronized public void onServiceConnected(ComponentName name, IBinder service) {
    			// 获得IPerson接口
    			iPerson = IPerson.Stub.asInterface(service);
    			if (iPerson != null)
    				try {
    					// RPC 方法调用
    					iPerson.setName("花郎");
    					iPerson.setAge(22);
    					String msg = iPerson.display();
    					// 显示方法调用返回值
    					Toast.makeText(RPCTest.this, msg, Toast.LENGTH_LONG)
    							.show();
    				} catch (RemoteException e) {
    					e.printStackTrace();
    				}
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    			// TODO Auto-generated method stub
    			
    		}
    		
    	};
    	//声明IPerson接口
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            btn = (Button)findViewById(R.id.Button01);
            btn.setOnClickListener(new OnClickListener()
            {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				Intent intent = new Intent();
    				intent.setAction("org.hualang.rpc.RPC_ACTION");
    				bindService(intent, conn, Service.BIND_AUTO_CREATE);
    			}
            	
            }
           );
        }
    }
    

     6、注意要在AndroidManifest.xml文件中注册Service

    		<service
    			android:name=".RemoteService">
    			<intent-filter>
    				<action android:name="org.hualang.rpc.RPC_ACTION"/>
    			</intent-filter>
    		</service>

     

    运行结果如下:当点击按钮后,就会弹出远程调用后的Toast


     

     

     


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3