当前位置:  编程技术>移动开发
本页文章导读:
    ▪Socket通讯总结        Socket通信总结 (转)------------------前言------------------开发了这么多年,发现最困难的程序开发就是通讯系统。 其他大部分系统,例如CRM/CMS/权限框架/MIS之类的,无论怎么复杂,基本上都.........
    ▪ Gallery跟GridView浅析、宫格图的实现        Gallery和GridView浅析、宫格图的实现 转载自 http://liangruijun.blog.51cto.com/3061169/647355 一.Gallery的简介     Gallery (画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,.........
    ▪ 跨平台开发:初探PhoneGap腾挪开发框架(4)       跨平台开发:初探PhoneGap移动开发框架(4) 转载自http://mobile.51cto.com/android-229213_3.htm   改进HelloWorld程序 接下来我们改进下这个程序,实现的功能是我们可以在文本框里输入名字,然后点确定.........

[1]Socket通讯总结
    来源: 互联网  发布时间: 2014-02-18
Socket通信总结
(转)
------------------

前言

------------------

开发了这么多年,发现最困难的程序开发就是通讯系统。



其他大部分系统,例如CRM/CMS/权限框架/MIS之类的,无论怎么复杂,基本上都能够本地代码本地调试,性能也不太重要。(也许这个就是.net的企业级开发的战略吧)



可是来到通讯系统,一切变得困难复杂。原因实在太多了,如:

•性能永远是第一位:有时候一个if判断都要考虑性能,毕竟要损耗一个CPU指令,而在通讯系统服务器,每秒钟都产生上百万级别的通讯量,这样一个if就浪费了1个毫秒了。
•系统环境极其恶劣:所有我们可以想象的恶意攻击、异常输入等都要考虑;
•网络说断就断:在socket环境下,客户端可以以各种理由断开链接,而且服务器根本不会知道,连一个流水作业的业务逻辑都无法保证正常执行,因此需要设计各种辅助的协议、架构去监督。
•各种网络链接问题:例如代理、防火墙等等。。。
经过了1年的跌跌撞撞,我总算收获了点有用的经验,本文先从设计角度介绍一些我在Socket编程中的经验,下一篇在放出源代码。



------------------

现有的Socket编程资源

------------------

1. 首选推荐开源的XMPP框架,也就是Google的Gtalk的开源版本。里面的架构写的非常漂亮。特点就是:简洁、清晰。



2. 其次推荐LumaQQ.net,这套框架本身写的一般般,但是腾讯的服务器非常的猛,这样必然导致客户端也要比较猛。通过学习这套框架,能够了解腾讯的IM传输协议设计,而且他们的协议是TCP/UDP结合,一举两得。



3. 最后就是DotMsn。这个写的实在很一般般,而且也主要针对了MSN的协议特点。是能够学习到一点点的框架知识的,不过要有所鉴别。



------------------

Socket的选择

------------------

在Java,到了Java5终于出现了异步编程,NIO,于是各种所谓的框架冒了出来,例如MINA, xsocket等等;而在.NET,微软一早就为我们准备好了完善的Socket模型。主要包括:同步Socket、异步Socket;我还听说了.net 3.x之后,异步的Socket内置了完成端口。综合各种模型的性能,我总结如下:



1. 如果是短链接,使用同步socket。例如http服务器、转接服务器等等。



2. 如果是长链接,使用异步socket。例如通讯系统(QQ / Fetion)、webgame等。



3. .net的异步socket的连接数性能在 7500/s(每秒并发7500个socket链接)。而听说完成端口在1.5w所有。但是我到目前还没有正式见过所谓的完成端口,不知道到底有多牛逼。



4. 我听说了java的NIO性能在5000/s所有,我们项目内部也进行了链接测试,在4000~5000比较稳定,当然如果代码调优之后,能提高一点点。



------------------

TCP Socket协议定义

------------------

本文从这里开始,主要介绍TCP的socket编程。

新手们(例如当初的我),第一次写socket,总是以为在发送方压入一个"Helloworld",接收方收到了这个字符串,就“精通”了Socket编程了。而实际上,这种编程根本不可能用在现实项目,因为:



1. socket在传输过程中,helloworld有可能被拆分了,分段到达客户端),例如 hello   +   world,一个分段就是一个包(Package),这个就是分包问题。



2. socket在传输过成功,不同时间发送的数据包有可能被合并,同时到达了客户端,这个就是黏包问题。例如发送方发送了hello+world,而接收方可能一次就接受了helloworld.



3. socket会自动在每个包后面补n个 0x0 byte,分割包。具体怎么去补,这个我就没有深入了解。



4. 不同的数据类型转化为byte的长度是不同的,例如int转为byte是4位(int32),这样我们在制作socket协议的时候要特别小心了。具体可以使用以下代码去测试:

代码
        public void test()
        {
            int myInt = 1;
            byte[] bytes = new byte[1024];
            BinaryWriter writer = new BinaryWriter(new MemoryStream(bytes));
            writer.Write(myInt);
            writer.Write("j");
            writer.Close();
        }



尽管socket环境如此恶劣,但是TCP的链接也至少保证了:

•包发送顺序在传输过程中是不会改变的,例如发送方发送 H E L L,那么接收方一定也是顺序收到H E L L,这个是TCP协议承诺的,因此这点成为我们解决分包、黏包问题的关键。
•如果发送方发送的是helloworld, 传输过程中分割成为hello+world,那么TCP保证了在hello与world之间没有其他的byte。但是不能保证helloworld和下一个命令之间没有其他的byte。


因此,如果我们要使用socket编程,就一定要编写自己的协议。目前业界主要采取的协议定义方式是:包头+包体长度+包体。具体如下:



1. 一般包头使用一个int定义,例如int = 173173173;作用是区分每一个有效的数据包,因此我们的服务器可以通过这个int去切割、合并包,组装出完整的传输协议。有人使用回车字符去分割包体,例如常见的SMTP/POP协议,这种做法在特定的协议是没有问题的,可是如果我们传输的信息内容自带了回车字符串,那么就糟糕了。所以在设计协议的时候要特别小心。



2. 包体长度使用一个int定义,这个长度表示包体所占的比特流长度,用于服务器正确读取并分割出包。



3. 包体就是自定义的一些协议内容,例如是对像序列化的内容(现有的系统已经很常见了,使用对象序列化、反序列化能够极大简化开发流程,等版本稳定后再转入手工压入byte操作)。



一个实际编写的例子:比如我要传输2个整型 int = 1, int = 2,那么实际传输的数据包如下:

   173173173               8                  1         2

|------包头------|----包体长度----|--------包体--------|

这个数据包就是4个整型,总长度 = 4*4  = 16。



说说我走的弯路:

我曾经偷懒,使用特殊结束符去分割包体,这样传输的数据包就不需要指名长度了。可是后来高人告诉我,如果使用特殊结束符去判断包,性能会损失很大,因为我们每次读取一个byte,都要做一次if判断,这个性能损失是非常严重的。所以最终还是走主流,使用以上的结构体。





------------------

Socket接收的逻辑概述

------------------

针对了我们的数据包设计+socket的传输特点,我们的接收逻辑主要是:

1. 寻找包头。这个包头就是一个int整型。但是写代码的时候要非常注意,一个int实际上占据了4个byte,而可悲的是这4个byte在传输过程中也可能被socket 分割了,因此读取判断的逻辑是:

•判断剩余长度是否大于4
•读取一个int,判断是否包头,如果是就跳出循环。
•如果不是包头,则倒退3个byte,回到第一点。
•如果读取完毕也没有找到,则有可能包头被分割了,因此当前已读信息压入接收缓存,等待下一个包到达后合并判断。
2. 读取包体长度。由于长度也是一个int,因此判断的时候也要小心,同上。

3. 读取包体,由于已知包体长度,因此读取包体就变得非常简单了,只要一直读取到长度未知,剩余的又回到第一条寻找包头。



这个逻辑不要小看,就这点东西忙了我1天时间。而非常奇怪的是,我发现c#写的socket,似乎没有我说的这么复杂逻辑。大家可以看看LumaQQ.net / DotMsn等,他们的socket接收代码都非常简单。我猜想:要么是.net的socket进行了优化,不会对int之类的进行分割传输;要么就是作者偷懒,随便写点代码开源糊弄一下。




------------------

Socket服务器参数概述

------------------

我在开篇也说了,Socket服务器的环境是非常糟糕了,最糟糕的就是客户端断线之后服务器没有收到通知。 因为socket断线这个也是个信息,也要从客户端传递到我们socket服务器。有可能网络阻塞了,导致服务器连断开的通知都没有收到。

因此,我们写socket服务器,就要面对2个环境:

1. 服务器在处理业务逻辑中的任何时候都会收到Exception, 任何时候都会因为链接中断而断开。

2. 服务器接收到的客户端请求可以是任意字符串,因此在处理业务逻辑的时候,必须对各种可能的输入都判断,防止恶意攻击。



针对以上几点,我们的服务器设计必须包含以下参数:

1. 客户端链接时间记录:主要判断客户端空连接情况,防止连接数被恶意占用。

2. 客户端请求频率记录:要防止客户端频繁发送请求导致服务器负荷过重。

3. 客户端错误记录:一次错误可能导致服务器产生一次exception,而这个性能损耗是非常严重的,因此要严格监控客户端的发送协议错误情况。

4. 客户端发送信息长度记录:有可能客户端恶意发送非常长的信息,导致服务器处理内存爆满,直接导致宕机。



5. 客户端短时间暴涨:有可能在短时间内,客户端突然发送海量数据,直接导致服务器宕机。因此我们必须有对服务器负荷进行监控,一旦发现负荷过重,直接对请求的socket返回处理失败,例如我们常见的“404”。



6. 服务器短时间发送信息激增:有可能在服务器内部处理逻辑中,突然产生了海量的数据需要发送,例如游戏中的“群发”;因此必须对发送进行队列缓存,然后进行合并发送,减轻socket的负荷。





------------------

后记

------------------

本文从架构设计分析了一个socket服务器的设计要点。如果您有其他见解,欢迎留言与讨论。


--------------------------------------------

我们的最新动态 (Bamboo@pixysoft.net)

1.解决comet在多页面中冲突的问题.[2011-1-23]

2.优化部分后台逻辑代码.提升首页访问性能[2011-1-20]

3.网络Comet平台再次成功对接上线.[2011-1-9]

我们每天都在努力着!

作者:美丽人生
出处:http://zc22.cnblogs.com/
技术支持:reborn_zhang@hotmail.com

    
[2] Gallery跟GridView浅析、宫格图的实现
    来源: 互联网  发布时间: 2014-02-18
Gallery和GridView浅析、宫格图的实现

转载自 http://liangruijun.blog.51cto.com/3061169/647355

一.Gallery的简介

    Gallery (画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,并且可以响应事件显示信息。Gallery还可以和ImageSwitcher组件结合使用来实现一个通过缩略图来浏览图片的效果。

Gallery常用的XML属性

属性名称

描述

android:animationDuration

设置布局变化时动画的转换所需的时间(毫秒级)。仅在动画开始时计时。该值必须是整数,比如:100 。

android:gravity

指定在对象的X 和Y 轴上如何放置内容。指定一下常量中的一个或多个(使用 “| ”分割)

Constant

Value

Description

top

0x30

紧靠容器顶端,不改变其大小

bottom

0x50

紧靠容器底部,不改变其大小

left

0x03

紧靠容器左侧,不改变其大小

right

0x05

紧靠容器右侧,不改变其大小

center_vertical

0x10

垂直居中,不改变其大小

fill_vertical

0x70

垂直方向上拉伸至充满容器

center_horizontal

0x01

水平居中,不改变其大小

Fill_horizontal

0x07

水平方向上拉伸使其充满容器

center

0x11

居中对齐,不改变其大小

fill

0x77

在水平和垂直方向上拉伸,使其充满容器

clip_vertical

0x80

垂直剪切(当对象边缘超出容器的时候,将上下边缘超出的部分剪切掉)

clip_horizontal

0x08

水平剪切(当对象边缘超出容器的时候,将左右边缘超出的部分剪切掉)

 

android:spacing

图片之间的间距

android:unselectedAlpha

设置未选中的条目的透明度(Alpha) 。该值必须是float 类型,比如:“1.2 ”。

首先介绍Gallery单独使用的例子:

MainActivity.java

  • package  com.android.gallerydemo;  
  •  
  • import  android.app.Activity;  
  • import  android.content.Context;  
  • import  android.os.Bundle;  
  • import  android.view.View;  
  • import  android.view.ViewGroup;  
  • import  android.widget.AdapterView;  
  • import  android.widget.AdapterView.OnItemClickListener;  
  • import  android.widget.BaseAdapter;  
  • import  android.widget.Gallery;  
  • import  android.widget.ImageView;  
  • import  android.widget.Toast;  
  •  
  • public   class  MainActivity  extends  Activity {  
  •  
  •     private  Gallery gallery;  
  •      @Override  
  •      public   void  onCreate(Bundle savedInstanceState) {  
  •  
  •          super .onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •         gallery = (Gallery)findViewById(R.id.gallery);  
  •          //设置图片适配器  
  •         gallery.setAdapter( new  ImageAdapter( this ));  
  •          //设置监听器  
  •         gallery.setOnItemClickListener( new  OnItemClickListener() {  
  •           @Override  
  •           public   void  onItemClick(AdapterView<?>parent, View v,  int  position,  long  id) {  
  •             Toast.makeText(MainActivity. this ,  "点击了第" +(position+ 1 )+ "张图片" , Toast.LENGTH_LONG).show();  
  •          }  
  •      });  
  •     }  
  • }  
  •  
  • class  ImageAdapter  extends  BaseAdapter{  
  •    //声明Context   
  •    private  Context context;  
  •    //图片源数组  
  •    private  Integer[] imageInteger={  
  •          R.drawable.pic1,  
  •          R.drawable.pic2,  
  •          R.drawable.pic3,  
  •          R.drawable.pic4,  
  •          R.drawable.pic5,  
  •          R.drawable.pic6,  
  •          R.drawable.pic7  
  •   };  
  •     
  •    //声明 ImageAdapter  
  •    public  ImageAdapter(Context c){  
  •      context = c;  
  •   }  
  •  
  •    @Override  
  •    //获取图片的个数  
  •    public   int  getCount() {  
  •       return  imageInteger.length;  
  •   }  
  •  
  •    @Override  
  •    //获取图片在库中的位置  
  •    public  Object getItem( int  position) {  
  •  
  •       return  position;  
  •   }  
  •  
  •    @Override  
  •    //获取图片在库中的位置  
  •    public   long  getItemId( int  position) {  
  •       // TODO Auto-generated method stub  
  •       return  position;  
  •  }  
  •  
  •    @Override  
  •    public  View getView( int  position, View convertView, ViewGroup parent) {  
  •  
  •      ImageView imageView =  new  ImageView(context);  
  •       //给ImageView设置资源  
  •      imageView.setImageResource(imageInteger[position]);  
  •       //设置比例类型  
  •      imageView.setScaleType(ImageView.ScaleType.FIT_XY);  
  •       //设置布局 图片128x192显示  
  •      imageView.setLayoutParams( new  Gallery.LayoutParams( 128 ,  192 ));  
  •       return  imageView;  
  •   }  
  • }  
  •  
  •  
  • main.xml

  • <? xml   version = "1.0"   encoding = "utf-8" ?>  
  • < Gallery   xmlns:android = "http://schemas.android.com/apk/res/android"    
  •        android:id = "@+id/gallery"          
  •        android:layout_width = "fill_parent"  
  •        android:layout_height = "wrap_content"  
  •        android:gravity = "center_vertical"  
  •        android:background = "?android:galleryItemBackground"  
  • />  
  •  
  • 效果图:

     Gallery和ImageSwitcher组件结合使用的例子:

    MainActivity.java

  • package  com.android.gallerytest;  
  •  
  • import  android.app.Activity;  
  • import  android.content.Context;  
  • import  android.os.Bundle;  
  • import  android.view.View;  
  • import  android.view.ViewGroup;  
  • import  android.view.Window;  
  • import  android.view.animation.AnimationUtils;  
  • import  android.widget.AdapterView;  
  • import  android.widget.BaseAdapter;  
  • import  android.widget.Gallery;  
  • import  android.widget.ImageSwitcher;  
  • import  android.widget.ImageView;  
  • import  android.widget.AdapterView.OnItemSelectedListener;  
  • import  android.widget.Gallery.LayoutParams;  
  • import  android.widget.ViewSwitcher.ViewFactory;  
  •  
  • public   class  MainActivity  extends  Activity  implements  OnItemSelectedListener,  
  •         ViewFactory {  
  •       
  •      private  ImageSwitcher mSwitcher;  
  •      //大图片对应的缩略图源数组  
  •      private  Integer[] mThumbIds = { R.drawable.sample_thumb_0,  
  •             R.drawable.sample_thumb_1, R.drawable.sample_thumb_2,  
  •             R.drawable.sample_thumb_3, R.drawable.sample_thumb_4,  
  •             R.drawable.sample_thumb_5, R.drawable.sample_thumb_6,  
  •             R.drawable.sample_thumb_7 };  
  •      //大图片源数组  
  •      private  Integer[] mImageIds = { R.drawable.sample_0, R.drawable.sample_1,  
  •             R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4,  
  •             R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7 };  
  •  
  •      @Override  
  •      public   void  onCreate(Bundle savedInstanceState) {  
  •          super .onCreate(savedInstanceState);  
  •          //设置窗口无标题  
  •         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  •         setContentView(R.layout.main);  
  •         mSwitcher = (ImageSwitcher) findViewById(R.id.switcher);  
  •          //注意在使用一个ImageSwitcher之前,  
  •          //一定要调用setFactory方法,要不setImageResource这个方法会报空指针异常。  
  •         mSwitcher.setFactory( this );  
  •          //设置动画效果  
  •         mSwitcher.setInAnimation(AnimationUtils.loadAnimation( this ,  
  •                 android.R.anim.fade_in));  
  •         mSwitcher.setOutAnimation(AnimationUtils.loadAnimation( this ,  
  •                 android.R.anim.fade_out));  
  •  
  •         Gallery g = (Gallery) findViewById(R.id.gallery);  
  •           
  •          //添加OnItemSelectedListener监听器  
  •         g.setAdapter( new  ImageAdapter( this ));  
  •         g.setOnItemSelectedListener( this );  
  •  
  •     }  
  •      //创建内部类ImageAdapter  
  •      public   class  ImageAdapter  extends  BaseAdapter {  
  •          public  ImageAdapter(Context c) {  
  •             mContext = c;  
  •         }  
  •          public   int  getCount() {  
  •              return  mThumbIds.length;  
  •         }  
  •          public  Object getItem( int  position) {  
  •              return  position;  
  •         }  
  •          public   long  getItemId( int  position) {  
  •              return  position;  
  •         }  
  •          public  View getView( int  position, View convertView, ViewGroup parent) {  
  •             ImageView i =  new  ImageView(mContext);  
  •  
  •             i.setImageResource(mThumbIds[position]);  
  •              //设置边界对齐  
  •             i.setAdjustViewBounds( true );  
  •              //设置布局参数  
  •             i.setLayoutParams( new  Gallery.LayoutParams(  
  •                     LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));  
  •              //设置背景资源  
  •             i.setBackgroundResource(R.drawable.picture_frame);  
  •              return  i;  
  •         }  
  •          private  Context mContext;  
  •     }  
  •  
  •      @Override  
  •      //实现onItemSelected()方法,更换图片  
  •      public   void  onItemSelected(AdapterView<?> adapter, View v,  int  position,  
  •              long  id) {  
  •          //设置图片资源  
  •         mSwitcher.setImageResource(mImageIds[position]);  
  •     }  
  •  
  •      @Override  
  •      public   void  onNothingSelected(AdapterView<?> arg0) {  
  •  
  •     }  
  •  
  •      @Override  
  •      //实现makeView()方法,为ImageView设置布局格式  
  •      public  View makeView() {  
  •         ImageView i =  new  ImageView( this );  
  •          //设置背景颜色  
  •         i.setBackgroundColor( 0xFF000000 );  
  •          //设置比例类型  
  •         i.setScaleType(ImageView.ScaleType.FIT_CENTER);  
  •          //设置布局参数  
  •         i.setLayoutParams( new  ImageSwitcher.LayoutParams(  
  •                 LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
  •          return  i;  
  •     }  
  •  main.xml

  • <? xml   version = "1.0"   encoding = "utf-8" ?>  
  • < RelativeLayout   xmlns:android = "http://schemas.android.com/apk/res/android"    
  •      android:layout_width = "fill_parent"    
  •      android:layout_height = "fill_parent"  
  •      >       
  •      < ImageSwitcher    
  •          android:id = "@+id/switcher"  
  •          android:layout_width = "fill_parent"  
  •          android:layout_height = "fill_parent"  
  •          android:layout_alignParentTop = "true"  
  •          android:layout_alignParentLeft = "true"  
  •          />      
  •      < Gallery  
  •          android:id = "@+id/gallery"  
  •          android:background = "#55000000"  
  •          android:layout_width = "fill_parent"  
  •          android:layout_height = "60dp"  
  •          android:layout_alignParentBottom = "true"  
  •          android:layout_alignParentLeft = "true"  
  •          android:gravity = "center_vertical"  
  •          android:spacing = "16dp"  
  •          />  
  • </ RelativeLayout >  
  •      
  • 效果图:

     二.GridView的简介

        GridView(网格视图)是按照行列的方式来显示内容的,一般用于显示图片,图片等内容,比如实现九宫格图,用GridView是首选,也是最简单的。主要用于设置Adapter。

    GridView常用的XML属性:

     

    属性名称

    描述

    android:columnWidth

    设置列的宽度。

    android:gravity

    设置此组件中的内容在组件中的位置。可选的值有: top 、 bottom 、 left 、 right 、 center_vertical 、 fill_vertical 、 center_horizontal 、 fill_horizontal 、 center 、 fill 、 clip_vertical 可以多选,用“ | ”分开。

    android:horizontalSpacing

    两列之间的间距。

    android:numColumns

    设置列数。

    android:stretchMode

    缩放模式。

    android:verticalSpacing

    两行之间的间距。

    下面有三个例子,第一个是只显示图片的,第二个是显示图片文字的(这里的图片是Android系统自带的图片),第三个是显示自定义的图片文字。前 面两个例子的实现都不是很难,第三个例子的实现有些复杂,学习GridView的时候,就想着能不能自定义自己喜欢的图片加上文字,在网上找些资料,一般 都是第二个例子的形式的,最后在视频学习上找到了能实现自定义自己的图片的例子。自己就照着例子去学习,修改成了第三个例子。

    第一个例子:

    MainActivity.java

  • package com.android.gridview.activity;
  • import android.app.Activity;
  • import android.content.Context;
  • import android.os.Bundle;
  • import android.view.View;
  • import android.view.ViewGroup;
  • import android.widget.AdapterView;
  • import android.widget.AdapterView.OnItemClickListener;
  • import android.widget.BaseAdapter;
  • import android.widget.GridView;
  • import android.widget.ImageView;
  • import android.widget.Toast;
  • public class MainActivity extends Activity {
  • @Override
  • public void onCreate(Bundle savedInstanceState) {
  • super .onCreate(savedInstanceState);
  • setContentView(R.layout.main);
  • GridView gv = (GridView)findViewById(R.id.GridView1);
  • //为GridView设置适配器
  • gv.setAdapter( new MyAdapter( this ));
  • //注册监听事件
  • gv.setOnItemClickListener( new OnItemClickListener()
  • {
  • public void onItemClick(AdapterView<?> parent, View v, int position, long id)
  • {
  • Toast.makeText(MainActivity. this , "pic" + position, Toast.LENGTH_SHORT).show();
  • }
  • });
  • }
  • }
  • //自定义适配器
  • class MyAdapter extends BaseAdapter{
  • //上下文对象
  • private Context context;
  • //图片数组
  • private Integer[] imgs = {
  • R.drawable.pic0, R.drawable.pic1, R.drawable.pic2,
  • R.drawable.pic3, R.drawable.pic4, R.drawable.pic5,
  • R.drawable.pic6, R.drawable.pic7, R.drawable.pic8,
  • R.drawable.pic0, R.drawable.pic1, R.drawable.pic2,
  • R.drawable.pic3, R.drawable.pic4, R.drawable.pic5,
  • R.drawable.pic6, R.drawable.pic7, R.drawable.pic8,
  • };
  • MyAdapter(Context context){
  • this .context = context;
  • }
  • public int getCount() {
  • return imgs.length;
  • }
  • public Object getItem( int item) {
  • return item;
  • }
  • public long getItemId( int id) {
  • return id;
  • }
  • //创建View方法
  • public View getView( int position, View convertView, ViewGroup parent) {
  • ImageView imageView;
  • if (convertView == null ) {
  • imageView = new ImageView(context);
  • imageView.setLayoutParams( new GridView.LayoutParams( 75 , 75 )); //设置ImageView对象布局
  • imageView.setAdjustViewBounds( false ); //设置边界对齐
  • imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); //设置刻度的类型
  • imageView.setPadding( 8 , 8 , 8 , 8 ); //设置间距
  • }
  • else {
  • imageView = (ImageView) convertView;
  • }
  • imageView.setImageResource(imgs[position]); //为ImageView设置图片资源
  • return imageView;
  • }
  • }
  • main.xml

  • <? xml version = "1.0" encoding = "utf-8" ?>
  • < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
  • android:orientation = "vertical"
  • android:layout_width = "fill_parent"
  • android:layout_height = "fill_parent"
  • >
  • < GridView
  • android:id = "@+id/GridView1"
  • android:layout_width = "wrap_content"
  • android:layout_height = "wrap_content"
  • android:columnWidth = "90dp"
  • android:numColumns = "3"
  • android:verticalSpacing = "10dp"
  • android:horizontalSpacing = "10dp"
  • android:stretchMode = "columnWidth"
  • android:gravity = "center"
  • />
  • </ LinearLayout >
  • 效果图:

     

    第二个例子:

    MainActivity.java

  • package com.android.gridview2.activity;
  • import java.util.ArrayList;
  • import java.util.HashMap;
  • import java.util.List;
  • import java.util.Map;
  • import android.app.Activity;
  • import android.os.Bundle;
  • import android.widget.GridView;
  • import android.widget.SimpleAdapter;
  • public class MainActivity extends Activity {
  • private GridView gv;
  • @Override
  • protected void onCreate(Bundle savedInstanceState) {
  • // TODO Auto-generated method stub
  • super .onCreate(savedInstanceState);
  • setContentView(R.layout.gridview);
  • //准备要添加的数据条目
  • List<Map<String, Object>> items = new ArrayList<Map<String,Object>>();
  • for ( int i = 0 ; i < 9 ; i++) {
  • Map<String, Object> item = new HashMap<String, Object>();
  • item.put( "imageItem" , R.drawable.icon); //添加图像资源的ID
  • item.put( "textItem" , "icon" + i); //按序号添加ItemText
  • items.add(item);
  • }
  • //实例化一个适配器
  • SimpleAdapter adapter = new SimpleAdapter( this ,
  • items,
  • R.layout.grid_item,
  • new String[]{ "imageItem" , "textItem" },
  • new int []{R.id.image_item, R.id.text_item});
  • //获得GridView实例
  • gv = (GridView)findViewById(R.id.mygridview);
  • //为GridView设置适配器
  • gv.setAdapter(adapter);
  • }
  • }
  • gridview.xml

  • <? xml version = "1.0" encoding = "utf-8" ?>
  • < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
  • android:layout_width = "wrap_content"
  • android:layout_height = "wrap_content"
  • >
  • < GridView
  • android:id = "@+id/mygridview"
  • android:numColumns = "3"
  • android:gravity = "center_horizontal"
  • android:layout_width = "wrap_content"
  • android:layout_height = "wrap_content"
  • android:stretchMode = "columnWidth"
  • />
  • </ LinearLayout >
  • grid_item.xml

  • <? xml version = "1.0" encoding = "utf-8" ?>
  • < RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
  • android:id = "@+id/RelativeLayout1"
  • android:layout_width = "wrap_content"
  • android:layout_height = "fill_parent"
  • android:paddingBottom = "6dip"
  • >
  • < ImageView
  • android:id = "@+id/image_item"
  • android:layout_width = "wrap_content"
  • android:layout_height = "wrap_content"
  • android:layout_centerHorizontal = "true"
  • />
  • < TextView
  • android:id = "@+id/text_item"
  • android:layout_below = "@+id/image_item"
  • android:layout_height = "wrap_content"
  • android:layout_width = "wrap_content"
  • android:layout_centerHorizontal = "true"
  • />
  • </ RelativeLayout >
  • 效果图:

     

    第三个例子:

    MainActivity.java

  • package com.android.gridview3;
  • import java.util.ArrayList;
  • import java.util.List;
  • import android.app.Activity;
  • import android.content.Context;
  • import android.os.Bundle;
  • import android.view.LayoutInflater;
  • import android.view.View;
  • import android.view.ViewGroup;
  • import android.widget.AdapterView;
  • import android.widget.BaseAdapter;
  • import android.widget.GridView;
  • import android.widget.ImageView;
  • import android.widget.TextView;
  • import android.widget.Toast;
  • import android.widget.AdapterView.OnItemClickListener;
  • public class MainActivity extends Activity
  • {
  • private GridView gridView;
  • //图片的文字标题
  • private String[] titles = new String[]
  • { "pic1" , "pic2" , "pic3" , "pic4" , "pic5" , "pic6" , "pic7" , "pic8" , "pic9" };
  • //图片ID数组
  • private int [] images = new int []{
  • R.drawable.pic1, R.drawable.pic2, R.drawable.pic3,
  • R.drawable.pic4, R.drawable.pic5, R.drawable.pic6,
  • R.drawable.pic7, R.drawable.pic8,R.drawable.pic9
  • };
  • @Override
  • public void onCreate(Bundle savedInstanceState){
  • super .onCreate(savedInstanceState);
  • setContentView(R.layout.main);
  • gridView = (GridView) findViewById(R.id.gridview);
  • PictureAdapter adapter = new PictureAdapter(titles, images, this );
  • gridView.setAdapter(adapter);
  • gridView.setOnItemClickListener( new OnItemClickListener()
  • {
  • public void onItemClick(AdapterView<?> parent, View v, int position, long id)
  • {
  • Toast.makeText(MainActivity. this , "pic" + (position+ 1 ), Toast.LENGTH_SHORT).show();
  • }
  • });
  • }
  • }
  • //自定义适配器
  • class PictureAdapter extends BaseAdapter{
  • private LayoutInflater inflater;
  • private List<Picture> pictures;
  • public PictureAdapter(String[] titles, int [] images, Context context)
  • {
  • super ();
  • pictures = new ArrayList<Picture>();
  • inflater = LayoutInflater.from(context);
  • for ( int i = 0 ; i < images.length; i++)
  • {
  • Picture picture = new Picture(titles[i], images[i]);
  • pictures.add(picture);
  • }
  • }
  • @Override
  • public int getCount()
  • {
  • if ( null != pictures)
  • {
  • return pictures.size();
  • } else
  • {
  • return 0 ;
  • }
  • }
  • @Override
  • public Object getItem( int position)
  • {
  • return pictures.get(position);
  • }
  • @Override
  • public long getItemId( int position)
  • {
  • return position;
  • }
  • @Override
  • public View getView( int position, View convertView, ViewGroup parent)
  • {
  • ViewHolder viewHolder;
  • if (convertView == null )
  • {
  • convertView = inflater.inflate(R.layout.picture_item, null );
  • viewHolder = new ViewHolder();
  • viewHolder.title = (TextView) convertView.findViewById(R.id.title);
  • viewHolder.image = (ImageView) convertView.findViewById(R.id.image);
  • convertView.setTag(viewHolder);
  • } else
  • {
  • viewHolder = (ViewHolder) convertView.getTag();
  • }
  • viewHolder.title.setText(pictures.get(position).getTitle());
  • viewHolder.image.setImageResource(pictures.get(position).getImageId());
  • return convertView;
  • }
  • }
  • class ViewHolder
  • {
  • public TextView title;
  • public ImageView image;
  • }
  • class Picture
  • {
  • private String title;
  • private int imageId;
  • public Picture()
  • {
  • super ();
  • }
  • public Picture(String title, int imageId)
  • {
  • super ();
  • this .title = title;
  • this .imageId = imageId;
  • }
  • public String getTitle()
  • {
  • return title;
  • }
  • public void setTitle(String title)
  • {
  • this .title = title;
  • }
  • public int getImageId()
  • {
  • return imageId;
  • }
  • public void setImageId( int imageId)
  • {
  • this .imageId = imageId;
  • }
  • }
  • main.xml

  • <? xml version = "1.0" encoding = "utf-8" ?>
  • < GridView xmlns:android = "http://schemas.android.com/apk/res/android"
  • android:id = "@+id/gridview"
  • android:layout_width = "fill_parent"
  • android:layout_height = "fill_parent"
  • android:columnWidth = "90dp"
  • android:numColumns = "auto_fit"
  • android:verticalSpacing = "10dp"
  • android:horizontalSpacing = "10dp"
  • android:stretchMode = "columnWidth"
  • android:gravity = "center"
  • />
  • picture_item.xml

  • <? xml version = "1.0" encoding = "utf-8" ?>
  • < LinearLayout
  • xmlns:android = "http://schemas.android.com/apk/res/android"
  • android:id = "@+id/root"
  • android:orientation = "vertical"
  • android:layout_width = "wrap_content"
  • android:layout_height = "wrap_content"
  • android:layout_marginTop = "5dp"
  • >
  • < ImageView
  • android:id = "@+id/image"
  • android:layout_width = "100dp"
  • android:layout_height = "150dp"
  • android:layout_gravity = "center"
  • android:scaleType = "fitXY"
  • android:padding = "4dp"
  • />
  • < TextView
  • android:id = "@+id/title"
  • android:layout_width = "wrap_content"
  • android:layout_height = "wrap_content"
  • android:layout_gravity = "center"
  • android:gravity = "center_horizontal"
  • />
  • </ LinearLayout >
  • 效果图:


        
    [3] 跨平台开发:初探PhoneGap腾挪开发框架(4)
        来源: 互联网  发布时间: 2014-02-18
    跨平台开发:初探PhoneGap移动开发框架(4)

    转载自http://mobile.51cto.com/android-229213_3.htm

     

    改进HelloWorld程序

    接下来我们改进下这个程序,实现的功能是我们可以在文本框里输入名字,然后点确定按钮后,弹出提示窗口显示Hello+你输入的名字。修改程序代码如下:

    >    
        
    <html>    
        
      <head>    
        
        <meta name="viewport" content="width=320; user-scalable=no" />    
        
        <meta http-equiv="Content-type" content="text/html; charset=utf-8">    
        
        <title>PhoneGaptitle>    
        
                  <script type="text/javascript" charset="utf-8" src="/blog_article/phonegap.js">script>            
        
                  <script type="text/javascript" charset="utf-8">    
        
                  var displayHello = function() {     
        
                            var name =      document.getElementById("firstname").value;     
        
                            navigator.notification.alert("name" + name);     
        
                }     
        
       script>    
        
      head>    
        
      <body onload="init();" id="bdy" >    
        
                <div id="txt">    
        
                <input   type="text" name="firstname" id="firstname" />    
        
                div>    
        
                <div id ="btn">    
        
        <a href="#"  onclick="displayHello();">Say Helloa>    
        
                div>    
        
            div>    
        
      body>    
        
    html>   
     

    如果你懂得HTML和Javascript的话,上面的程序实在容易理解。其中我们添加了一个名为firstname的文本框,并且在按钮的 onclick事件中调用的displayHello()方法中通过document.getElementById的Javascript方法获得了用 户输入的名字,然后同样用navigator.notification.alert的方法输出结果,输入的界面和输出的结果如下图所示:

    总结

    通过PhoneGap这套开源框架对开发移动设备SDK的封装,我们今后在开发移动应用时,只需要调用PhoneGap封装好的API,结合已有的 Java、HTML、CSS和Javascript技术,就可以很方便地进行开发了,更多的资料请查看PhoneGap的帮助文档。


        
    最新技术文章:
    ▪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添加多个可点击的文本
    NOSQL iis7站长之家
    ▪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