[转载]倒计时的实现方案-类似限时抢购商品等-Android开发源码下载-eoe Android开发者社区_Android开发论坛

mikel阅读(964)

[转载]倒计时的实现方案-类似限时抢购商品等-Android开发源码下载-eoe Android开发者社区_Android开发论坛.

网上有很多关于倒计时的实现方案.也不知道我的这个方案大家有没有提到,我在此帖出来,希望能够给大家提供一个参考.

应用平台: Android;
应用案例: 大量商品的限时抢购等.

请看下图:

类似于这样的倒计时,不知道大家有没有遇到过,大家又能想到哪些方案?????
1、每一秒到服务器上面去取一次数据?
2、每一秒,通过一个Handler去循环遍历,对每一条去刷新一次时间控件?
3、还是大家有其它的想法。

上述两种方案都不可取:
1、网络连接有时间差,况且数据访问量大的情况,服务器没法承受。
2、 循环遍历可行,但是要在数据量少的情况下,如果数据量过大,那么会卡屏,对系统内存的占用也较高。

我给大家的方案是对Android 系统中 DigitalClock 进行一次封装。
通过继承以下方法并改变内部的实现。
@Override
protected void onAttachedToWindow() {
mTickerStopped = false;
super.onAttachedToWindow();
mHandler = new Handler();

  /**
* requests a tick on the next hard-second boundary
*/
mTicker = new Runnable() {
public void run() {
if (mTickerStopped)
return;
long currentTime = System.currentTimeMillis();
if (currentTime / 1000 == endTime / 1000 – 5 * 60) {      // currentTime 是超过现在的当前时间。能过这个运算,达到倒计时的效果
mClockListener.remainFiveMinutes();
}
long distanceTime = endTime – currentTime;
distanceTime /= 1000;
if (distanceTime == 0) {
setText(“00:00:00”);
onDetachedFromWindow();
mClockListener.timeEnd();
} else if (distanceTime < 0) {
setText(“00:00:00”);
} else {
setText(dealTime(distanceTime));
}
invalidate();
long now = SystemClock.uptimeMillis();
long next = now + (1000 – now % 1000);
mHandler.postAtTime(mTicker, next);
}
};
mTicker.run();
}
大家可以看看Android 系统中 DigitalClock 的这个方法的实现:
@Override
protected void onAttachedToWindow() {
mTickerStopped = false;
super.onAttachedToWindow();
mHandler = new Handler();

/**
* requests a tick on the next hard-second boundary
*/
mTicker = new Runnable() {
public void run() {
if (mTickerStopped) return;
mCalendar.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(mFormat, mCalendar));
invalidate();
long now = SystemClock.uptimeMillis();
long next = now + (1000 – now % 1000);
mHandler.postAtTime(mTicker, next);
}
};
mTicker.run();
}
跟上述是截然不同的。

不多说,有兴趣的下去研究研究。谢谢。
源代码如下:
TimeSale.rar (144.61 KB, 下载次数: 351)

[转载]GridView的下拉刷新上拉加载以及ListView和ScrollView等...-Android开发源码下载-eoe Android开发者社区_Android开发论坛

mikel阅读(1134)

[转载](分享)GridView的下拉刷新上拉加载以及ListView和ScrollView等…-Android开发源码下载-eoe Android开发者社区_Android开发论坛.

之前网络上分享的一些ListView、ScrollView和GridView的下拉刷新以及上拉加载,但是GridView在小米2S手机以及 note II 、nexus4上面,都无法下拉刷新  但是在480×800的分辨率以下的机子上面缺可以实现下拉刷新的功能!~由于项目中需要实现Gridview的 下拉刷新和分页加载,因此个人修改了之前Gridview无法下拉刷新的实现,其实主要还是跟手机的密度有关系。
(该下拉刷新 上拉加载其实都是通过自定义的LinearLayout来实现的,具体看代码)

(本来是贴出代码的,但是貌似内容太长了,超过发帖子的字节了!)

其实主要修改的也是363行代码:

代码片段,双击复制
01
if (mAdapterView.getFirstVisiblePosition() == 0 && Math.abs(top - padding) <= 11) {

之前网上分享的都是<=8 而这个8其实是根据分辨率480×800的分辨率的手机密度算出来的,但是放在1280×720或者高分辨率中gridview就无法下拉刷新了,像 1280×720的分辨率的密度为2 而gridview的xml布局中的Android:verticalSpacing=”10dip”是10,密度2×10/2+1即为11(这里大于 11都行),(其实我也这里也不知道是怎么算密度,本人也是菜鸟,是位朋友告诉我的)。
看到网上好多都没解决该问题 因此我把网上共享的代码就稍微修改修改了!

如图:


截图是模拟器的,但是本人测试了 noteII   nexus4  小米2  的gridview都可以下拉刷新。(第一次发帖经验不足,重在分享,呵呵!)

下载地址:http://pan.baidu.com/s/1qWwbs9u

[转载]关于APK文件的MIME类型 | 应用开发笔记

mikel阅读(1102)

[转载]关于APK文件的MIME类型 | 应用开发笔记.

最近遇到一件奇怪的事情,把APK文件传到虚拟主机上,用浏览器访问下载时,提示404,文件不存在,可是FTP里看到文件明明就存在。搜索了一 下,得知在虚拟主机后台设置一下MIEI就可以解决,因为之前不知道APK的MIME该怎么填,APK又是压缩文件,结果就填了ZIP的 application/x-compressed。还真的能下载了,但是下载下来默认会把扩展名改为ZIP,于是又搜了下APK的MIME类型,结果是 application/vnd.Android.package-archive,现在问题解决。

© 2010, 冰冻鱼. 请尊重作者劳动成果,复制转载保留本站链接! 应用开发笔记

[转载]android 自动检测版本升级-Android开发实例教程-eoe Android开发者社区_Android开发论坛

mikel阅读(798)

[转载]android 自动检测版本升级-Android开发实例教程-eoe Android开发者社区_Android开发论坛.

eoeAndroid 推荐:
Android 自动检测
http://www.eoeandroid.com/thread-109730-1-1.html
Android版本检测 自动更新(一)
http://www.eoeandroid.com/thread-99266-1-1.html
Android版本检测 自动更新(二)
http://www.eoeandroid.com/thread-99271-1-1.html

在我们APP的开发中,往往都会遇到版本的升级,因为不可能有任何一个应用做的完美无缺,所以版本升级对APP应用来说是不可缺少的一部分.像新浪微博等 一些应用软件,三天两头提醒我升级.不过这样也很正常,就像android 升级一样,为了给用户提供更方便更人性化的操作.说下具体实现吧,不过我是参考别人的。不管对你们有没有帮助,总之对我有帮助啊,如果日后用到就直接 copy了.哈哈,不扯了。
首先看一个文件manifest文件.


我们可以很清楚的看到versionCode和versionName,我们一般用versionCode来实现,

实现原理很简单:服务器端有个serverVersion,我们本地有个localVersion.服务器端serverVersion>localVersion,这个时候我们就需要进行升级版本.原理大致就是这样。具体实现请看下面.


package com.jj.upgrade;
import com.jj.Service.UpdateService;
import android.app.AlertDialog;
import android.app.Application;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
/***
* MyApplication
*
* @author zhangjia
*
*/
public class MyApplication extends Application {
public static int localVersion = 0;// 本地安装版本
public static int serverVersion = 2;// 服务器版本
public static String downloadDir = "jj/";// 安装目录
@Override
public void onCreate() {
super.onCreate();
try {
PackageInfo packageInfo = getApplicationContext()
.getPackageManager().getPackageInfo(getPackageName(), 0);
localVersion = packageInfo.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
/***
* 在这里写一个方法用于请求获取服务器端的serverVersion.
*/
}
}

我们一般把全局的东西放到application里面.


public class MainActivity extends Activity {
private MyApplication myApplication;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

checkVersion();
}
/***
* 检查是否更新版本
*/
public void checkVersion() {
myApplication = (MyApplication) getApplication();
if (myApplication.localVersion &lt; myApplication.serverVersion) { // 发现新版本,提示用户更新 AlertDialog.Builder alert = new AlertDialog.Builder(this); alert.setTitle("软件升级") .setMessage("发现新版本,建议立即更新使用.") .setPositiveButton("更新", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent updateIntent = new Intent( MainActivity.this, UpdateService.class); updateIntent.putExtra( "app_name", getResources().getString( R.string.app_name)); startService(updateIntent); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alert.create().show(); } } } 

我们在运行应用的时候要checkVersion();进行检查版本是否要进行升级. 最主要的是UpdateService服务类,

 @Override public int onStartCommand(Intent intent, int flags, int startId) { app_name = intent.getStringExtra("app_name"); // 创建文件 FileUtil.createFile(app_name);// 创建文件 createNotification();// 首次创建 createThread();// 线程下载 return super.onStartCommand(intent, flags, startId); } 

创建路径及文件,这里就不介绍了,不明白了下载源码看. 首先我们先 看createNotification().这个方法:

 /*** * 创建通知栏 */ RemoteViews contentView; public void createNotification() { notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notification = new Notification(); notification.icon = R.drawable.ic_launcher;// 这个图标必须要设置,不然下面那个RemoteViews不起作用. // 这个参数是通知提示闪出来的值. notification.tickerText = "开始下载"; // // updateIntent = new Intent(this, MainActivity.class); // pendingIntent = PendingIntent.getActivity(this, 0, updateIntent, 0); // // // 这里面的参数是通知栏view显示的内容 // notification.setLatestEventInfo(this, app_name, "下载:0%", // pendingIntent); // // notificationManager.notify(notification_id, notification); /*** * 在这里我们用自定的view来显示Notification */ contentView = new RemoteViews(getPackageName(), R.layout.notification_item); contentView.setTextViewText(R.id.notificationTitle, "正在下载"); contentView.setTextViewText(R.id.notificationPercent, "0%"); contentView.setProgressBar(R.id.notificationProgress, 100, 0, false); notification.contentView = contentView; updateIntent = new Intent(this, MainActivity.class); updateIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); pendingIntent = PendingIntent.getActivity(this, 0, updateIntent, 0); notification.contentIntent = pendingIntent; notificationManager.notify(notification_id, notification); } 

上面实现的也不难理解.(主要是初始化Notification,用于提醒用户开始下载) 接着我们要看createThread方法

 /*** * 开线程下载 */ public void createThread() { /*** * 更新UI */ final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case DOWN_OK: // 下载完成,点击安装 Uri uri = Uri.fromFile(FileUtil.updateFile); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(uri, "application/vnd.android.package-archive"); pendingIntent = PendingIntent.getActivity( UpdateService.this, 0, intent, 0); notification.setLatestEventInfo(UpdateService.this, app_name, "下载成功,点击安装", pendingIntent); notificationManager.notify(notification_id, notification); stopSelf(); break; case DOWN_ERROR: notification.setLatestEventInfo(UpdateService.this, app_name, "下载失败", pendingIntent); break; default: stopSelf(); break; } } }; final Message message = new Message(); new Thread(new Runnable() { @Override public void run() { try { long downloadSize = downloadUpdateFile(down_url, FileUtil.updateFile.toString()); if (downloadSize &gt; 0) {
// 下载成功
message.what = DOWN_OK;
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
message.what = DOWN_ERROR;
handler.sendMessage(message);
}
}
}).start();
}

这个方法有点小多,不过我想大家都看的明白,我在这里简单说名一下:首先我们创建一个handler用于检测最后下载ok还是not ok.

下面我们开启了线程进行下载数据。
我们接着看downloadUpdateFile这个方法:


/***
* 下载文件
*
* @return
* @throws MalformedURLException
*/
public long downloadUpdateFile(String down_url, String file)
throws Exception {
int down_step = 5;// 提示step
int totalSize;// 文件总大小
int downloadCount = 0;// 已经下载好的大小
int updateCount = 0;// 已经上传的文件大小
InputStream inputStream;
OutputStream outputStream;
URL url = new URL(down_url);
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();
httpURLConnection.setConnectTimeout(TIMEOUT);
httpURLConnection.setReadTimeout(TIMEOUT);
// 获取下载文件的size
totalSize = httpURLConnection.getContentLength();
if (httpURLConnection.getResponseCode() == 404) {
throw new Exception("fail!");
}
inputStream = httpURLConnection.getInputStream();
outputStream = new FileOutputStream(file, false);// 文件存在则覆盖掉
byte buffer[] = new byte[1024];
int readsize = 0;
while ((readsize = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, readsize);
downloadCount += readsize;// 时时获取下载到的大小
/**
* 每次增张5%
*/
if (updateCount == 0
|| (downloadCount * 100 / totalSize - down_step) &gt;= updateCount) {
updateCount += down_step;
// 改变通知栏
// notification.setLatestEventInfo(this, "正在下载...", updateCount
// + "%" + "", pendingIntent);
contentView.setTextViewText(R.id.notificationPercent,
updateCount + "%");
contentView.setProgressBar(R.id.notificationProgress, 100,
updateCount, false);
// show_view
notificationManager.notify(notification_id, notification);
}
}
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
inputStream.close();
outputStream.close();
return downloadCount;
}

  源码下载

[转载]Android中visibility属性VISIBLE、INVISIBLE、GONE的区别-Android新手入门-eoe Android开发者社区_Android开发论坛

mikel阅读(920)

[转载]Android中visibility属性VISIBLE、INVISIBLE、GONE的区别-Android新手入门-eoe Android开发者社区_Android开发论坛.

Android开发中,大部分控件都有visibility这个属性,其属性有3个分别为“visible ”、“invisible”、“gone”。主要用来设置控制控件的显示和隐藏。有些人可能会疑惑Invisible和gone是有什么区别的???那么,我们带着这个疑问看下面:

其在XML文件和Java代码中设置如下:

可见(visible)
XML文件:Android:visibility=”visible”
Java代码:view.setVisibility(View.VISIBLE);

不可见(invisible)
XML文件:Android:visibility=”invisible”
Java代码:view.setVisibility(View.INVISIBLE);

隐藏(GONE)
XML文件:Android:visibility=”gone”
Java代码:view.setVisibility(View.GONE);

为了区别三者,我建了一个Dome进行演示,先上Dome的代码,演示后就知道它们的区别:


<!--?xml version="1.0" encoding="utf-8"?-->

<button></button>

<button>
</button><button>
</button>

后面三个Button只要是控制TextView的visibility的属性


package com.chindroid.visibility;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
/** TextView2 */
private TextView mainTV2 = null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//初始化数据
initData();
}
/** 初始化控件的方法 */
private void initData() {
mainTV2 = (TextView)findViewById(R.id.mainTV2);
}

/**
* MainActivity中响应<a class="relatedlink" target="_blank">按钮</a>点击事件的方法
*
* @param v
*/
public void mianOnClickListener(View v){
switch (v.getId()){
case R.id.mainBtn1:{ //按钮1的响应事件
//设置TextView2可见
mainTV2.setVisibility(View.VISIBLE);
break;
}
case R.id.mainBtn2:{ //按钮2的响应事件
//设置TextView2不可见
mainTV2.setVisibility(View.INVISIBLE);
break;
}
case R.id.mainBtn3:{ //按钮3的响应事件
//设置TextView2隐藏
mainTV2.setVisibility(View.GONE);
break;
}
default:
break;
}
}
}

由于程序一启动两个TextView都是可见的

当我们点击第1个按钮,把TextView2visibility属性设置为INVISIBLE时,程序如下如下图所示:

当我们点击第3个按钮,把TextView2visibility属性设置为GONE时,程序如下如下图所示:

当我们再点击第1个按钮,把TextView2visibility属性设置为VISIBLE时,TextView2又呈现出来了,如下图所示:

由上面的演示可知
VISIBLE:设置控件可见
INVISIBLE:设置控件不可见
GONE:设置控件隐藏

而INVISIBLE和GONE的主要区别是:当控件visibility属性为INVISIBLE时,界面保留了view控件所占有的空间;而控件属性为GONE时,界面则不保留view控件所占有的空间。

[转载]关于异常“The specified child already has a parent. You must call removeView"的解决(举例说明,附源码) - yaozq的android开发 - 博客频道 - CSDN.NET

mikel阅读(843)

[转载]关于异常“The specified child already has a parent. You must call removeView”的解决(举例说明,附源码) – yaozq的android开发 – 博客频道 – CSDN.NET.

Android开发过程中,有时会在不同情况下遇到同种问题:

 

  1. java.lang.IllegalStateException The specified child already has a parent. You must call removeView() on the child’s parent first.  

也就是非法状态异常,它说这个特定的child已经有一个parent了,你必须在这个parent中首先调用removeView()方法,才能继续你的内容。这里很明显这个child是一个View,一个子(childView必须依赖于父(parentView,如果你要使用这个child,则必须通过parent,而你如果就是硬想使用这个child,那么就得让这个childparent脱离父子关系(即removeView())……算了还是举个简单的例子来说明一下,省的我说的乱七八糟,你听的也晕。

新建一个项目,布局文件中仅包含一个TextView和一个ImageView,布局方式是线性布局(具体可以参考后面的源代码),运行的结果就是显示一个文本和一张图片,

 

ActivityonCreate()方法中,我们通常使用以下这种方式来使用布局文件main.xml

 

  1. setContentView(R.layout.main);  

这里为了解释今天要讲解的这个异常,换一种布局文件的使用方式,即把上面的那一行代码注释掉,换成以下代码:

//获取Infalter对象

 

  1. LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);  
  2. LinearLayout parent = (LinearLayout) inflater.inflate(R.layout.main, null);  
  3. ImageView child = (ImageView)parent.findViewById(R.id.child);          
  4. setContentView(parent);  

LayoutInflater为布局填充类,不明白的可以自己查,或者有机会我将在博客中介绍一下,然后是将main.xml文件inflateLinearLayout文件,再得到child,即ImageView。然后就是通过调用setContentView(parent)将这个布局main.xml显示出来,这时得到的效果和仅使用setContentView(R.layout.main)这句代码得到的效果一样。

下面的操作将会出现异常了,大家注意:

 

  1. setContentView(child);  

也就是将上文setContentView(parent),中的parent换成child。异常请看如下截图:

 

而这时在异常中它提示要再parent中调用removeView()。这里我们就听从指挥,在setContentView(child),之前添上一句parent.removeView(child),这时就不会再调用setContentView(child)就不会异常了,当然当前显示的将只是一幅图片了,而这时如果你调用setContentView(parent)的话将只显示文本内容,因为我们已经将child remove掉了嘛。

 

代码如下:

http://download.csdn.net/detail/yaolingrui/4129192

[转载]ListView详解之三 - 古老的陶罐 - 博客园

mikel阅读(1128)

[转载]ListView详解之三 – 古老的陶罐 – 博客园.

参考http://www.cnblogs.com/angeldevil/archive/2011/11/20/2255972.html

上上篇,我们使用了几次Adapter,如ArrayAdapter、SimpleAdapter;上篇,我们又见识了更多的Adapter,有点晕了,到底什么是Adapter?

一、Adapter的作用

Adapter是AdapterView视图与数据之间的桥梁,Adapter提供对数据的访问,也负责为每一项数据产生一个对应的View。其作用如下图所示:

看了这幅图,我想你大概明白什么是Adapter了,不过你肯定也有了新的疑问,不管你有没有,反正我是有过了。新疑问:这不是一直在讲ListView吗?那AdapterView是什么呢?

大概猜一下,它应该是所有要用到Adapter的View的父类吧。去开发文档里面一看,果然如此,看下图:

再点进去,看看listview:

这下更明白了吧!不过说实话,我现在更迷惑的是Android类的继承关系了,要说搞通所有类的继承关系,一下两下也不现实,先看看下面的Adapter的继承关系吧!

二、Adapter的继承结构

要了解Adapter的继承和派生关系了,还好前面了解了这点东西,http://www.cnblogs.com/fww330666557/archive/2012/01/11/2319613.html,以作参考。

然后在去看看Adapter:

什么?Adapter是一个接口?我一直以为它是类。

什么?接口可以派生类?“接口!=函数或方法”吗?http://www.cnblogs.com/huihui-gohay/archive/2009/12/13/1623070.html(这篇文章说了接口的问题,我没仔细看,你可以去看看)。

再确认一下,widget是个包,没学过java,到底什么是包?我的理解,跟一个文件差不多吧!

还有,要分清楚Adapter和AdapterView。

三、各个类的作用

下面的内容怎么说呢,有点繁杂,如果你有耐心,你就细细看吧,不过最好是先了解个大概,我们这里的关键任务是理解Adapter各个类之间的继承关系。

Adapter

Adapter做为这个继承结构的最顶层的基接口,定义了Adapter要实现的基本方法:

复制代码
public interface Adapter { 
    //注册一个Observer,当Adapter所表示的数据改变时会通知它,DataSetObserver是一个抽象类,定义了两个方法:onChanged与onInvalidated 
    void registerDataSetObserver(DataSetObserver observer); 
    //取消注册一个Observer 
    void unregisterDataSetObserver(DataSetObserver observer); 
    //所表示的数据的项数 
    int getCount(); 
    //返回指定位置的数据项 
    Object getItem(int position); 
    //返回指定位置的数据项的ID 
    long getItemId(int position); 
    //表示所有数据项的ID是否是稳定的,在BaseAdapter中默认返回了false,假设是不稳定的,在CursorAdapter中返回了true,Cursor中的_ID是不变的 
    boolean hasStableIds(); 
    //为每一个数据项产生相应的视图 
    View getView(int position, View convertView, ViewGroup parent); 
    //为了避免产生大量的View浪费内存,在Android中,AdapterView中的View是可回收的使用的。比如你有100项数据要显示,而你的屏幕一次只能显示10条数据,则 
    //只产生10个View,当往下拖动要显示第11个View时,会把第1个View的引用传递过去,更新里面的数据再显示,也就是说View可重用,只是更新视图中的数据用于显示新 
    //的一项,如果一个视图的视图类型是IGNORE_ITEM_VIEW_TYPE的话,则此视图不会被重用 
    static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE; 
    //获得相应位置的这图类型 
    int getItemViewType(int position); 
    //getView可以返回的View的类型数量。(在HeaderViewListAdapter中可以包含Header和Footer,getView可以返回Header、Footer及Adapter 
    //中的视图,但其getViewTypeCount的实现只是调用了内部Adapter的的getViewTypeCount,忽略了Header、Footer中的View Type,不懂。 
    int getViewTypeCount(); 
    static final int NO_SELECTION = Integer.MIN_VALUE; 
    boolean isEmpty(); 
}
复制代码

Adapter有两个子接口,ListAdapter(列表)与SpinnerAdapter(下拉列表),它们都只定义了少数方法。一般除WrapperListAdapter接口及其实现类只实现了ListAdapter外,都同时实现了这两个接口。

ListAdapter

//是否在ListAdapter中的所有项都enabled,即是否所有项都selectable和clickable 
public boolean areAllItemsEnabled(); 
//指定位置的项是否是enabled的 
boolean isEnabled(int position);

SpinnerAdapter

//产生相应位置下拉项的视图 
public View getDropDownView(int position, View convertView, ViewGroup parent);

BaseAdapter

一个抽象类,Adapter的基础实现类,一般作为其他实现类的基类,同时实现ListAdapter与SpinnerAdapter,提供了一些方法的默认实现:

复制代码
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { 
    //提供一些方法,当数据改变时调用注册的DataSetObserver的回调函数 
    private final DataSetObservable mDataSetObservable = new DataSetObservable(); 
    public boolean hasStableIds() { 
        return false; 
    } 
    public void registerDataSetObserver(DataSetObserver observer) { 
        mDataSetObservable.registerObserver(observer); 
    } 
    public void unregisterDataSetObserver(DataSetObserver observer) { 
        mDataSetObservable.unregisterObserver(observer); 
    } 
    //通知相关联的视图,相应的数据已经改变 
    public void notifyDataSetChanged() { 
        mDataSetObservable.notifyChanged(); 
    } 
    public void notifyDataSetInvalidated() { 
        mDataSetObservable.notifyInvalidated(); 
    } 
    public boolean areAllItemsEnabled() { 
        return true; 
    } 
    public boolean isEnabled(int position) { 
        return true; 
    } 
    //通过getView实现 
    public View getDropDownView(int position, View convertView, ViewGroup parent) { 
        return getView(position, convertView, parent); 
    } 
    public int getItemViewType(int position) { 
        return 0; 
    } 
    public int getViewTypeCount() { 
        return 1; 
    } 
    public boolean isEmpty() { 
        return getCount() == 0; 
    } 
}
复制代码

ArrayAdapter<T>

A concrete BaseAdapter that is backed by an array of arbitrary objects. By default this class expects that the provided resource id references a single TextView. If you want to use a more complex layout, use the constructors that also takes a field id. That field id should reference a TextView in the larger layout resource.

However the TextView is referenced, it will be filled with the toString() of each object in the array. You can add lists or arrays of custom objects. Override the toString() method of your objects to determine what text will be displayed for the item in the list.

To use something other than TextViews for the array display, for instance, ImageViews, or to have some of data besides toString() results fill the views, override getView() to return the type of view you want.

默认ArrayAdapter产生的视图期望一个TextView,或者也可以指定一个Layout并指定其中一个类型为TextView的资源的 ID,其底下的数据可以是任意类型,但显示的时候会调用其toString()方法,也就是说只能用TextView显示文字,如果想显示其他的数据,要 重写getView()

ArrayAdapter有5个构造函数:

复制代码
public ArrayAdapter(Context context, int textViewResourceId) { 
    init(context, textViewResourceId, 0, new ArrayList<T>()); 
} 
public ArrayAdapter(Context context, int resource, int textViewResourceId) { 
    init(context, resource, textViewResourceId, new ArrayList<T>()); 
} 
public ArrayAdapter(Context context, int textViewResourceId, T[] objects) { 
    init(context, textViewResourceId, 0, Arrays.asList(objects)); 
} 
public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) { 
    init(context, resource, textViewResourceId, Arrays.asList(objects)); 
} 
public ArrayAdapter(Context context, int textViewResourceId, List<T> objects) { 
    init(context, textViewResourceId, 0, objects); 
} 
public ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects) { 
    init(context, resource, textViewResourceId, objects); 
}
复制代码

最多有4个参数,分别为当前Context,layout(可省),TextView的ID与数据(可为数组或List),在构造函数中都调用了一个叫init的函数

复制代码
private void init(Context context, int resource, int textViewResourceId, List<T> objects) { 
       mContext = context; 
       mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       mResource = mDropDownResource = resource; 
       mObjects = objects; 
       mFieldId = textViewResourceId; 
   }
复制代码

 

分别赋值给类中的私有域,mInflater为LayoutInflater,产生相应项的视图。

类中有两个域保存数据

private ArrayList<T> mOriginalValues; 
private List<T> mObjects;

 

其中mOriginalValues用于过滤数据时保存过滤前的数据,将过滤后的数据存入mObjects。

在ArrayAdapter中还定义了add,insert,remove,clear函数用于改变数据,并定义了一个布尔变量 mNotifyChange用于表示用这些函数改变数据后是否通知视图(调用notifyDataSetChanged,调用这个函数时会把 mNotifyChange置为true。

一些函数的实现:

复制代码
public int getCount() { 
    return mObjects.size(); 
} 
public T getItem(int position) { 
    return mObjects.get(position); 
} 
public int getPosition(T item) { 
    return mObjects.indexOf(item); 
} 
public long getItemId(int position) { 
    return position; 
} 
public View getView(int position, View convertView, ViewGroup parent) { 
    return createViewFromResource(position, convertView, parent, mResource); 
} 
public View getDropDownView(int position, View convertView, ViewGroup parent) { 
    return createViewFromResource(position, convertView, parent, mDropDownResource); 
}
复制代码

可以看到getView和getDropDownView都通过调用createViewFromResourse来产生视图。

复制代码
private View createViewFromResource(int position, View convertView, ViewGroup parent, 
           int resource) { 
       View view; 
       TextView text; 
 
       if (convertView == null) { 
           view = mInflater.inflate(resource, parent, false); 
       } else { 
           view = convertView; 
       } 
 
       try { 
           if (mFieldId == 0) { 
               //  If no custom field is assigned, assume the whole resource is a TextView 
               text = (TextView) view; 
           } else { 
               //  Otherwise, find the TextView field within the layout 
               text = (TextView) view.findViewById(mFieldId); 
           } 
       } catch (ClassCastException e) { 
           Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); 
           throw new IllegalStateException( 
                   "ArrayAdapter requires the resource ID to be a TextView", e); 
       } 
 
       T item = getItem(position); 
       if (item instanceof CharSequence) { 
           text.setText((CharSequence)item); 
       } else { 
           text.setText(item.toString()); 
       } 
 
       return view; 
   }
复制代码

在 createViewFromResource中,首先判断convertView是否存在,若不存在则inflate一个,然后判断mFieldID是 否为0,若为0则表示传递给ArrayAdapter的资源ID为一TextView,否则是传递了一Layout,mFieldID为此Layout中 TextView的ID。然后通过getItem取得相应位置的数据项,判断是否是CharSequence的实例,如果是直接setText,否则调用 其toString()函数,可以ArrayAdapter默认只能给TextVext设置字符串,若要使用其他视图,需要重载getView或 getDropDownView,一般情况下会继承BaseAdapter自定义自己的Adapter。

在ArrayAdapter中,还有一静态函数

public static ArrayAdapter<CharSequence> createFromResource(Context context, 
            int textArrayResId, int textViewResId) { 
        CharSequence[] strings = context.getResources().getTextArray(textArrayResId); 
        return new ArrayAdapter<CharSequence>(context, textViewResId, strings); 
    }

读取资源文件中定义的字符数组作为数据生成ArrayAdapter,可以看到只能用TextView视图,而不可以指定一Layout再指定Layout中一个TextView的ID。

在ArrayAdapter中还定义了一个 ArrayFilter,继承自Filter,用于过滤数据项(当ListView有焦点时,通过键盘输入字符来进行列表项的过滤),其过滤方法为传入一 CharSequence,判断相应数据项是否以此CharSequence开头,若不是则用空格分割些数据项,判断分割后的各字符串是否以此 CharSequence开头,若是则保留(若数据不是CharSequence则调用其toString())。如果传入的CharSequence为 null或长度为0则不过滤。

 

CursorAdapter

 

用于显示Cursor中的数据。

 

在构造函数中可传递一参数autoRequery表示当cursor的数据改变时是否自动调用cursor的requery()以保持视图数据为最新的。

此类中重写了hasStableIds(),返回true。

public boolean hasStableIds() { 
    return true; 
}

在CursorAdapter中,重写的getView及getDropDownView判断传入的convertView是否为null,若为null及相应地调用newView()或newDropDownView()来生成一个视图,而newDropDownView()只有一条语句 return newView(context, cursor, parent);所以最后都是调用newView(),newView()为abstract的,需要由子类重写。

当通过newView()产生一个View之后,会调用 bindView(v, mContext, mCursor);将cursor中的数据绑定到newView()产生的View之中,此方法同样为abstract的。
CursorAdapter实现了接口CursorFilter.CursorFilterClient中的方法
//改变cursor指向的数据
public void changeCursor(Cursor cursor)


//将cursor转变为CharSequence,返回""或调用cursor.toString()

public CharSequence convertToString(Cursor cursor)

//过滤数据

public Cursor runQueryOnBackgroundThread(CharSequence constraint)


ResourceCursorAdapter

如类名所示,该类继承自CursorAdapter,通过XML产生Views,该类只是简单地重写了一些函数,通过LayoutInflater.inflate将XML转换为View

复制代码
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) { 
    return mInflater.inflate(mLayout, parent, false); 
} 
 
@Override
public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) { 
    return mInflater.inflate(mDropDownLayout, parent, false); 
}
复制代码

SimpleCursorAdapter

一个ResourceCursorAdapter的简单实现类,用于把cursor中相应的列映射为XML定义的视图中的TextView和ImageView。

该类中定义了一个接口

public static interface ViewBinder { 
    boolean setViewValue(View view, Cursor cursor, int columnIndex); 
}

 

用于设置把cursor中的列映射为视图的方法。

在SimpleCursorAdapter中重写了bindView,控制cursor到视图的绑定,其定义如下

复制代码
@Override
    public void bindView(View view, Context context, Cursor cursor) { 
        final ViewBinder binder = mViewBinder; 
        final int count = mTo.length; 
        final int[] from = mFrom; 
        final int[] to = mTo; 
  
        for (int i = 0; i < count; i++) { 
            final View v = view.findViewById(to[i]); 
            if (v != null) { 
                boolean bound = false; 
                if (binder != null) { 
                    bound = binder.setViewValue(v, cursor, from[i]); 
                } 
  
                if (!bound) { 
                    String text = cursor.getString(from[i]); 
                    if (text == null) { 
                        text = ""; 
                    } 
  
                    if (v instanceof TextView) { 
                        setViewText((TextView) v, text); 
                    } else if (v instanceof ImageView) { 
                        setViewImage((ImageView) v, text); 
                    } else { 
                        throw new IllegalStateException(v.getClass().getName() + " is not a " + 
                                " view that can be bounds by this SimpleCursorAdapter"); 
                    } 
                } 
            } 
        } 
    }
复制代码

 

可以看到,首先检查类中的私有域mViewBinder是否为null(默认为null,可通过setViewBinder)设置,为不为null 则通过binder.setViewValue(v, cursor, from[i]); 进行绑定,这个函数若返回true则绑定成功,若返回false则通过SimpleCursorAdapter的规则绑定,判断相应的View是否为 TextView或ImageView,若是则绑定,否则抛出异常。

由些可以看到,我们可以自定义一个类实现SimpleCursorAdapter.ViewBinder,然后通过setViewBinder来改变bindView的结果。

SimpleAdapter

一个BaseAdapter的实现类,用于绑定数据到一个XML定义的视图中。数据类型为ArrayList<Map<String, ?>>。

SimpleAdapter也实现了Filter接口用于数据的过滤,过滤方法类似ArrayAdapter,只是其数据类型为Map<String,?>,要判断Map中的每一项,若任意一顶符合要求就保留。

SimpleAdapter也是通过bindView函数进行数据的绑定,同SimpleCursorAdapter一 样,SimpleAdapter也定义了一个相同的内部接口ViewBinder,在bindView中,首先判断是否通过setViewBinder设 置了ViewBinder,若设置了则调用其setViewValue进行数据绑定,如果没有设置其setViewValue返回了false,则进行下 面的处理:依次判断View是否为Checkable,TextView,ImageView并进行相应的处理,可见默认情况下 SimpleAdapter也是处理TextView与ImageView,当然可以setViewBinder。

WrapperListAdapter

继承自ListAdapder的接口,所以也是一个ListAdapter,同时里面嵌入了另一个ListAdapter,只定义了一个函数用于取得嵌入的ListAdapter

public ListAdapter getWrappedAdapter();

HeaderViewListAdapter

继承自WrapperListAdapter,当你使用的ListView有页首(Header Views)或页尾(Footer Views)时使用。此类被设计用来作为一个基类,一般不需要使用。

类中定义了两个ArrayList用于保存页首和页尾

ArrayList<ListView.FixedViewInfo> mHeaderViewInfos; 
ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
这两个域不为null,在构造函数中判断,如果给这两个域赋值的参数为null,则将他们赋于值 HeaderViewListAdapter.EMPTY_INFO_LIST,其定义为
static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST = 
        new ArrayList<ListView.FixedViewInfo>();

其中ListView.FixedViewInfo的定义为

public class FixedViewInfo { 
    public View view;ListAdapter#getItem(int)}. 
    public Object data; 
    public boolean isSelectable; 
}

该类重定义了getCount,areAllItemsEnabled等函数,把 mHeaderViewInfos,mFooterViewInfos同时包括在内。而hasStableIds,getItemViewType与 getViewTypeCount只考虑了其内嵌的ListAdapter

本篇完结。

[转载]FastJson 示例 及问题 - 心lu历程 - ITeye技术网站

mikel阅读(1004)

[转载]FastJson 示例 及问题 – 心lu历程 – ITeye技术网站.

不能以内部类的形式,使用parSEObject方法,会报:com.alibaba.fastjson.JSONException: create instance error

===========================================================================

http://www.cnblogs.com/zhenmingliu/archive/2011/12/29/2305775.html
http://871421448.iteye.com/blog/1581876
http://blog.sina.com.cn/s/blog_4f925fc30102egx0.html

有这个,解析应该不是问题了

package com.shihuan.test.myfastjson.vo;

import java.util.Date;

public class MyUser {

private Long userid;
private String username;
private boolean sex;
private Date birthday;

public MyUser() {
}

public Long getUserid() {
return userid;
}

public void setUserid(Long userid) {
this.userid = userid;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public boolean isSex() {
return sex;
}

public void setSex(boolean sex) {
this.sex = sex;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}

MyGroupUser.java代码如下:
package com.shihuan.test.myfastjson.vo;

import java.util.ArrayList;
import java.util.List;

public class MyGroupUser {

private Long groupid;
private String groupname;
private List<MyUser> listuser = new ArrayList<MyUser>();

public MyGroupUser() {
}

public Long getGroupid() {
return groupid;
}

public void setGroupid(Long groupid) {
this.groupid = groupid;
}

public String getGroupname() {
return groupname;
}

public void setGroupname(String groupname) {
this.groupname = groupname;
}

public List<MyUser> getListuser() {
return listuser;
}

public void setListuser(List<MyUser> listuser) {
this.listuser = listuser;
}
}

MyGroupSetUser.java代码如下:
package com.shihuan.test.myfastjson.vo;

import java.util.HashSet;
import java.util.Set;

public class MyGroupSetUser {

private Long groupsetid;
private String groupsetname;
private Set<MyUser> setuser = new HashSet<MyUser>();

public MyGroupSetUser() {
}

public Long getGroupsetid() {
return groupsetid;
}

public void setGroupsetid(Long groupsetid) {
this.groupsetid = groupsetid;
}

public String getGroupsetname() {
return groupsetname;
}

public void setGroupsetname(String groupsetname) {
this.groupsetname = groupsetname;
}

public Set<MyUser> getSetuser() {
return setuser;
}

public void setSetuser(Set<MyUser> setuser) {
this.setuser = setuser;
}
}

MyGroupMapUser.java代码如下:
package com.shihuan.test.myfastjson.vo;

import java.util.HashMap;
import java.util.Map;

public class MyGroupMapUser {

private Long groupmapid;
private String groupmapname;
private Map<String, MyUser> mapuser = new HashMap<String, MyUser>();

public MyGroupMapUser() {
}

public Long getGroupmapid() {
return groupmapid;
}

public void setGroupmapid(Long groupmapid) {
this.groupmapid = groupmapid;
}

public String getGroupmapname() {
return groupmapname;
}

public void setGroupmapname(String groupmapname) {
this.groupmapname = groupmapname;
}

public Map<String, MyUser> getMapuser() {
return mapuser;
}

public void setMapuser(Map<String, MyUser> mapuser) {
this.mapuser = mapuser;
}
}

MyTestJson.java代码如下:
package com.shihuan.test.myfastjson.mytest;

import com.shihuan.core.framework.utils.DateHelper;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.parser.Feature;

import com.shihuan.test.myfastjson.vo.MyGroupMapUser;
import com.shihuan.test.myfastjson.vo.MyGroupSetUser;
import com.shihuan.test.myfastjson.vo.MyGroupUser;
import com.shihuan.test.myfastjson.vo.MyUser;

public class MyTestJson {

public static void main(String[] args) {
MyUser myUser = new MyUser();
myUser.setUserid(1L);
myUser.setUsername("shihuan");
myUser.setSex(true);
myUser.setBirthday(new Date());
String myuserjson = JSON.toJSONString(myUser, SerializerFeature.WriteDateUseDateFormat);
System.out.println(myuserjson);
String myuserjsondateformat = JSON.toJSONStringWithDateFormat(myUser, "yyyy-MM-dd", SerializerFeature.WriteDateUseDateFormat);
System.out.println(myuserjsondateformat);
String myuserjsondateformathm = JSON.toJSONStringWithDateFormat(myUser, "yyyy-MM-dd HH:mm:ss.SSS", SerializerFeature.WriteDateUseDateFormat);
System.out.println(myuserjsondateformathm);
MyUser myJsonUser = JSON.parseObject(myuserjson, MyUser.class);
System.out.println(myJsonUser.getUserid() + " -- " + myJsonUser.getUsername() + " -- " + myJsonUser.getBirthday() + " -- " + myJsonUser.isSex());
MyUser myJsonUserDateformat = JSON.parseObject(myuserjson, MyUser.class, Feature.AllowISO8601DateFormat);
System.out.println(myJsonUserDateformat.getUserid() + " -- " + myJsonUserDateformat.getUsername() + " -- " + DateHelper.getFormatString(myJsonUserDateformat.getBirthday()) + " -- " + myJsonUserDateformat.isSex());
System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
MyUser myUser1 = new MyUser();
myUser1.setUserid(1L);
myUser1.setUsername("shihuan1");
myUser1.setSex(true);
myUser1.setBirthday(new Date());
MyUser myUser2 = new MyUser();
myUser2.setUserid(2L);
myUser2.setUsername("shihuan2");
myUser2.setSex(false);
myUser2.setBirthday(new Date());
List<MyUser> listmyusers = new ArrayList<MyUser>();
listmyusers.add(myUser1);
listmyusers.add(myUser2);
//List -> JSON array
String listmyusersjson= JSON.toJSONString(listmyusers, false);   //第二个参数表示是否格式化输出
        System.out.println(listmyusersjson);
        //JSON array -> List
        List<MyUser> myUserList = JSON.parseArray(listmyusersjson, MyUser.class);
        for (MyUser myUserTmp : myUserList) {
        System.out.println(myUserTmp.getUserid() + " -- " + myUserTmp.getUsername() + " -- " + myUserTmp.isSex() + " -- " + myUserTmp.getBirthday());
        }
        System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
        System.out.println("复合List对象的VO对象开始......");
MyGroupUser myGroupUser = new MyGroupUser();
myGroupUser.setGroupid(1L);
myGroupUser.setGroupname("gshihuan");
myGroupUser.setListuser(listmyusers);
String mygroupuserjson = JSON.toJSONString(myGroupUser, SerializerFeature.WriteDateUseDateFormat);
System.out.println(mygroupuserjson);
MyGroupUser myJsonGroupUser = JSON.parseObject(mygroupuserjson, MyGroupUser.class);
System.out.println(myJsonGroupUser.getGroupid() + " -- " + myJsonGroupUser.getGroupname() + " -- " + myJsonGroupUser.getListuser().get(0).getUserid() + "&" + myJsonGroupUser.getListuser().get(0).getUsername() + "&" + myJsonGroupUser.getListuser().get(0).getBirthday() + "&" + myJsonGroupUser.getListuser().get(0).isSex() + " -- " + myJsonGroupUser.getListuser().get(1).getUserid() + "&" + myJsonGroupUser.getListuser().get(1).getUsername() + "&" + myJsonGroupUser.getListuser().get(1).getBirthday() + "&" + myJsonGroupUser.getListuser().get(1).isSex());
System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
System.out.println("复合Set对象的VO对象开始......");
Set<MyUser> setObjData = new HashSet<MyUser>();
setObjData.add(myUser1);
setObjData.add(myUser2);
MyGroupSetUser myGroupSetUser = new MyGroupSetUser();
myGroupSetUser.setGroupsetid(1L);
myGroupSetUser.setGroupsetname("gsetshihuan");
myGroupSetUser.setSetuser(setObjData);
String mygroupsetuserjson = JSON.toJSONString(myGroupSetUser, SerializerFeature.WriteDateUseDateFormat);
System.out.println(mygroupsetuserjson);
MyGroupSetUser myJsonGroupSetUser = JSON.parseObject(mygroupsetuserjson, MyGroupSetUser.class);
System.out.println(myJsonGroupSetUser.getGroupsetid() + " -- " + myJsonGroupSetUser.getGroupsetname());
for(Iterator<MyUser> myUserIter = myJsonGroupSetUser.getSetuser().iterator(); myUserIter.hasNext();){
MyUser nbUserObj = myUserIter.next();
System.out.println(nbUserObj.getUserid() + "&" + nbUserObj.getUsername() + "&" + nbUserObj.isSex() + "&" + nbUserObj.getBirthday());
}
System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
System.out.println("复合Map对象的VO对象开始......");
Map<String, MyUser> myUserMap = new HashMap<String, MyUser>();
myUserMap.put("1", myUser1);
myUserMap.put("2", myUser2);
MyGroupMapUser myGroupMapUser = new MyGroupMapUser();
myGroupMapUser.setGroupmapid(1L);
myGroupMapUser.setGroupmapname("gmapshihuan");
myGroupMapUser.setMapuser(myUserMap);
String mygroupmapuserjson = JSON.toJSONString(myGroupMapUser, SerializerFeature.WriteDateUseDateFormat);
System.out.println(mygroupmapuserjson);
MyGroupMapUser myJsonGroupMapUser = JSON.parseObject(mygroupmapuserjson, MyGroupMapUser.class);
System.out.println(myJsonGroupMapUser.getGroupmapid() + " -- " + myJsonGroupMapUser.getGroupmapname());
Map<String, MyUser> myUserMapData = myJsonGroupMapUser.getMapuser();
for(Object obj : myUserMapData.keySet()) { 
   String key = (String)obj; 
   MyUser value = (MyUser)myUserMapData.get(key); 
   System.out.println(key + " : " + value.getUserid() + "&" + value.getUsername() + "&" + value.isSex() + "&" + value.getBirthday()); 
}
for(Entry<String, MyUser> userMapData : myJsonGroupMapUser.getMapuser().entrySet()) { 
   Entry entry = (Entry)userMapData; 
   String key = (String) entry.getKey(); 
   MyUser value = (MyUser) entry.getValue(); 
   System.out.println(key + " : " + value.getUserid() + "&" + value.getUsername() + "&" + value.isSex() + "&" + value.getBirthday()); 
}
System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
//Map -> JSON
        Map<String, MyUser> map = new HashMap<String, MyUser>();
        map.put("a", myUser1);
        map.put("b", myUser2);
        String mapjson = JSON.toJSONString(map, false);
        System.out.println(mapjson);
        //JSON -> Map
        Map<String, MyUser> map1 = (Map<String, MyUser>)JSON.parse(mapjson);
        for (String key : map1.keySet()) {
        System.out.println(key + " : " + map1.get(key));
        }
       
        System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
       
        String[] arrStrs = {"a", "b", "c"};
        String jsonarrStrs = JSON.toJSONString(arrStrs, false);
        System.out.println(jsonarrStrs);
        JSONArray jsonArray1 = JSON.parseArray(jsonarrStrs);
        for (Object o : jsonArray1) {
        System.out.println(o);
        }
        System.out.println(jsonArray1);
       
        System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
       
        MyUser[] arrMyUsers = {myUser1, myUser2};
        String jsonarrMyUsers = JSON.toJSONString(arrMyUsers, false);
        System.out.println(jsonarrMyUsers);
        JSONArray jsonArray2 = JSON.parseArray(jsonarrMyUsers);
        for (Object o : jsonArray2) {
        System.out.println(o);
        }
        System.out.println(jsonArray2);
       
        System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
       
        Map zzmap = new HashMap();
        zzmap.put("a", "aaa");
        zzmap.put("b", "bbb");
        zzmap.put("c", "ccc");
        String zzmapjson = JSON.toJSONString(zzmap);
        System.out.println(zzmapjson);
        Map zzmapobj = JSON.parseObject(zzmapjson);
        for (Object o : zzmap.entrySet()) {
        Map.Entry<String, String> entry = (Map.Entry<String, String>)o;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
}

}

运行结果如下:
{"birthday":"2012-12-08 13:34:29","sex":true,"userid":1,"username":"shihuan"}
{"birthday":"2012-12-08","sex":true,"userid":1,"username":"shihuan"}
{"birthday":"2012-12-08 13:34:29.921","sex":true,"userid":1,"username":"shihuan"}
1 -- shihuan -- Sat Dec 08 13:34:29 CST 2012 -- true
1 -- shihuan -- 2012-12-08 -- true
-------------------------------------------------------------------------------------------------------------------------------------
[{"birthday":1354944870421,"sex":true,"userid":1,"username":"shihuan1"},{"birthday":1354944870421,"sex":false,"userid":2,"username":"shihuan2"}]
1 -- shihuan1 -- true -- Sat Dec 08 13:34:30 CST 2012
2 -- shihuan2 -- false -- Sat Dec 08 13:34:30 CST 2012
-------------------------------------------------------------------------------------------------------------------------------------
复合List对象的VO对象开始......
{"groupid":1,"groupname":"gshihuan","listuser":[{"birthday":"2012-12-08 13:34:30","sex":true,"userid":1,"username":"shihuan1"},{"birthday":"2012-12-08 13:34:30","sex":false,"userid":2,"username":"shihuan2"}]}
1 -- gshihuan -- 1&shihuan1&Sat Dec 08 13:34:30 CST 2012&true -- 2&shihuan2&Sat Dec 08 13:34:30 CST 2012&false
-------------------------------------------------------------------------------------------------------------------------------------
复合Set对象的VO对象开始......
{"groupsetid":1,"groupsetname":"gsetshihuan","setuser":[{"birthday":"2012-12-08 13:34:30","sex":true,"userid":1,"username":"shihuan1"},{"birthday":"2012-12-08 13:34:30","sex":false,"userid":2,"username":"shihuan2"}]}
1 -- gsetshihuan
2&shihuan2&false&Sat Dec 08 13:34:30 CST 2012
1&shihuan1&true&Sat Dec 08 13:34:30 CST 2012
-------------------------------------------------------------------------------------------------------------------------------------
复合Map对象的VO对象开始......
{"groupmapid":1,"groupmapname":"gmapshihuan","mapuser":{"1":{"birthday":"2012-12-08 13:34:30","sex":true,"userid":1,"username":"shihuan1"},"2":{"birthday":"2012-12-08 13:34:30","sex":false,"userid":2,"username":"shihuan2"}}}
1 -- gmapshihuan
2 : 2&shihuan2&false&Sat Dec 08 13:34:30 CST 2012
1 : 1&shihuan1&true&Sat Dec 08 13:34:30 CST 2012
2 : 2&shihuan2&false&Sat Dec 08 13:34:30 CST 2012
1 : 1&shihuan1&true&Sat Dec 08 13:34:30 CST 2012
-------------------------------------------------------------------------------------------------------------------------------------
{"a":{"birthday":1354944870421,"sex":true,"userid":1,"username":"shihuan1"},"b":{"birthday":1354944870421,"sex":false,"userid":2,"username":"shihuan2"}}
b : {"birthday":1354944870421,"sex":false,"userid":2,"username":"shihuan2"}
a : {"birthday":1354944870421,"sex":true,"userid":1,"username":"shihuan1"}
-------------------------------------------------------------------------------------------------------------------------------------
["a","b","c"]
a
b
c
["a","b","c"]
-------------------------------------------------------------------------------------------------------------------------------------
[{"birthday":1354944870421,"sex":true,"userid":1,"username":"shihuan1"},{"birthday":1354944870421,"sex":false,"userid":2,"username":"shihuan2"}]
{"birthday":1354944870421,"sex":true,"userid":1,"username":"shihuan1"}
{"birthday":1354944870421,"sex":false,"userid":2,"username":"shihuan2"}
[{"birthday":1354944870421,"sex":true,"userid":1,"username":"shihuan1"},{"birthday":1354944870421,"sex":false,"userid":2,"username":"shihuan2"}]
-------------------------------------------------------------------------------------------------------------------------------------
{"a":"aaa","b":"bbb","c":"ccc"}
b--->bbb
c--->ccc
a--->aaa

[转载]Android开发之Http通信HttpURLConnection接口 - 一个Coding猪的故事 - 博客频道 - CSDN.NET

mikel阅读(939)

[转载]Android开发之Http通信HttpURLConnection接口 – 一个Coding猪的故事 – 博客频道 – CSDN.NET.

Android开发之Http通信HttpURLConnection接口

/*

 *  Android开发之Http通信HttpConnection接口

 *  北京Android俱乐部群:167839253

 *  Created on: 2012-5-9

 *  Author: blueeagle

 *  Email: liujiaxiang@gmail.com

 */

本文总结了一下《Android应用开发揭秘》里面关于Http通信部分HttpURLConnection接口的相关知识。

HttpURLConnection接口

Http通信协议中,使用的最多的就是GetPostGet请求可以获取静态页面,也可以把参数放在字串后面,传递给服务器。PostGet不同的是Post的参数不是放在URL字串的里面,而是放在http请求数据中。

HttpURLConnectionJAVA的标准类,继承自URLConnection类;

HttpURLConnectionURLConnection类都是抽象类,无法直接实例化对象。

其对象主要是通过URLopenConnection方法获得。

实例定义代码:

//构造一个URL对象
url = new URL(httpUrl);
//使用HttpURLConnection打开链接,urlConn就是实例对象
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();

openConnection方法只是创建了一个HttpURLConnection或者URLConnection的实例,并不进行真正的链接操作。
每次openConnection的时候都将创建一个新的实例。
因此在连接之前可以对该对象的属性进行设置。

//设置输入(输出)流
                                urlConn.setDoOutput(true);
                                urlConn.setDoInput(true);
                                //设置以POST方式
                                urlConn.setRequestMethod("POST");
                                //POST请求不能使用缓存
                                urlConn.setUseCaches(false);
//在连接完成之后可以关闭这个连接
                                urlConn.disconnect();

利用Get和Post方式来获取一个网页内容。
HttpURLConnection默认使用Get方式,如果要使用Post方式,则需要setRequestMethod设置。然后将我们要传递的参数内容通过weiteBytes方法写入数据流。
Get方式访问无参数的代码:

public class HttpURLConnectionActivity02 extends Activity {
    /** Called when the activity is first created. */
         
        private final String DEBUG_TAG = "HttpURLConnectionActivityActivity";
    @Override
    public void onCreate(Bundle savedInstanceState)        {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);                
                TextView mTextView = (TextView)this.findViewById(R.id.myTextView);
                //http地址
                String httpUrl = "http://10.1.69.34/http1.jsp";
                //获得的数据
                String resultData = "";
                URL url = null;
                try
                {
                        //构造一个URL对象
                        url = new URL(httpUrl); 
                }
                catch (MalformedURLException e)
                {
                        Log.e(DEBUG_TAG, "MalformedURLException");
                }
                if (url != null)
                {
                        try
                        {
                                //使用HttpURLConnection打开连接
                                HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
                                //得到读取的内容(流)
                                InputStreamReader in = new InputStreamReader(urlConn.getInputStream());
                                // 为输出创建BufferedReader
                                BufferedReader buffer = new BufferedReader(in);
                                String inputLine = null;
                                //使用循环来读取获得的数据
                                while (((inputLine = buffer.readLine()) != null))
                                {
                                        //我们在每一行后面加上一个"\n"来换行
                                        resultData += inputLine + "\n";
 
                                }        
                                 
                                if ( !resultData.equals("") )
                                {
                                        mTextView.setText(resultData);
                                }
                                else
                                {
                                        mTextView.setText("读取的内容为NULL");
                                }
                                //关闭InputStreamReader
                                in.close();
                                //关闭http连接
                                urlConn.disconnect();
                                //设置显示取得的内容
 
                        }
                        catch (IOException e)
                        {
                                Log.e(DEBUG_TAG, "IOException");
                        }
                }
                else
                {
                        Log.e(DEBUG_TAG, "Url NULL");
                }
                //设置按键事件监听
                Button button_Back = (Button) findViewById(R.id.Button_back);
                /* 监听button的事件信息 */
                button_Back.setOnClickListener(new Button.OnClickListener() 
                {
                        public void onClick(View v)
                        {
                                /* 新建一个Intent对象 */
                                Intent intent = new Intent();
                                /* 指定intent要启动的类 */
                                intent.setClass(HttpURLConnectionActivity02.this, HttpURLConnectionActivity.class);
                                /* 启动一个新的Activity */
                                startActivity(intent);
                                /* 关闭当前的Activity */
                                HttpURLConnectionActivity02.this.finish();
                        }
                });
        }     
}

总结:
针对HTTP协议,简单来说:
GET方式是通过把参数键值对附加在url后面来传递的,是文本方式的。
在服务器端可以从’QUERY_STRING’这个变量中直接读取,效率较高,但缺乏安全性,也无法来处理复杂的数据,长度有限制。主要用于传递简单的参数。
POST方式:就传输方式讲参数会被打包在http报头中传输,可以是二进制的。
从CONTENT_LENGTH这个环境变量中读取,便于传送较大一些的数据,同时因为不暴露数据在浏览器的地址栏中,安全性相对较高,但

[转载]HttpURLConnection的使用 - - 博客频道 - CSDN.NET

mikel阅读(903)

[转载]HttpURLConnection的使用 – – 博客频道 – CSDN.NET.

	/*
	 * URL请求的类别分为二类,GET与POST请求。二者的区别在于: 
	 * a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet, 
	 * b:) post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
	 */
	
	URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro.do");
	HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();

	// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在
	// http正文内,因此需要设为true, 默认情况下是false;
	urlConn.setDoOutput(true);

	// 设置是否从httpUrlConnection读入,默认情况下是true;
	urlConn.setDoInput(true);

	// Post 请求不能使用缓存
	urlConn.setUseCaches(false);

	// 设定传送的内容类型是可序列化的java对象
	// (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
	urlConn.setRequestProperty("Content-type","application/x-java-serialized-object");

	// 设定请求的方法为"POST",默认是GET
	urlConn.setRequestMethod("POST");

	// 连接,上面对urlConn的所有配置必须要在connect之前完成,
	urlConn.connect();

	// 此处getOutputStream会隐含的进行connect (即:如同调用上面的connect()方法,
	// 所以在开发中不调用上述的connect()也可以)。
	OutputStream outStrm = urlConn.getOutputStream();
	
	// 现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。
	ObjectOutputStream oos = new ObjectOutputStream(outStrm);

	// 向对象输出流写出数据,这些数据将存到内存缓冲区中
	oos.writeObject(new String("我是测试数据"));

	// 刷新对象输出流,将任何字节都写入潜在的流中(些处为ObjectOutputStream)
	oos.flush();

	// 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中,
	// 再调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器
	oos.close();

	// 调用HttpURLConnection连接对象的getInputStream()函数,
	// 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。
	InputStream inStrm = urlConn.getInputStream(); // <===注意,实际发送请求的代码段就在这里
	
//----------------------------------
	/*
	 * Post传参的方法
	 */
	OutputStream os = urlConn.getOutputStream();
    String param = new String();
    param = "CorpID=123&LoginName=qqq&name=" + URLEncoder.encode("汉字","GBK"); ;
    os.write(param.getBytes());
    
//----------------------------------
    /*
     * 超时设置,防止 网络异常的情况下,可能会导致程序僵死而不继续往下执行
     */
    
    //JDK 1.5以前的版本,只能通过设置这两个系统属性来控制网络超时:
    //连接主机的超时时间(单位:毫秒)
    System.setProperty("sun.net.client.defaultConnectTimeout", "30000"); 
    //从主机读取数据的超时时间(单位:毫秒)
    System.setProperty("sun.net.client.defaultReadTimeout", "30000"); 

    //在JDK 1.5以后可以这样来设置超时时间
    HttpURLConnection urlCon = (HttpURLConnection)url.openConnection();
    urlCon.setConnectTimeout(30000);
    urlCon.setReadTimeout(30000);
    
//----------------------------------
    /*
     * 总结:
     * HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
     * 无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
     * 
     * 对HttpURLConnection对象的一切配置都必须要在connect()函数执行之前完成。
     * 而对outputStream的写操作,又必须要在inputStream的读操作之前。
     * 这些顺序实际上是由http请求的格式决定的。
     * 
     * 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,
     * 实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,
	 * 而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。
	 * 至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求
	 * 正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http
	 * 请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数
	 * 之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)
	 * 都是没有意义的了,执行这些操作会导致异常的发生。
     * 
     */