安卓客户端与服务器的通信及ListView、adapter、fastjson的使用


在安卓开发的过程中,网络通信模块必不可少,尤其对于任何一个具有商用价值的应用,都离不开网络通信。今天我来谈谈我对安卓中网络访问、以及常见的ListView用法。

加入我们实现如下这个功能,但界面上显示的文字都是通过网络来获取的,在后续的文章里,我还会谈谈图片的两种加载方式,以及上传到服务器等,这里先掠过。




后台的服务器端的代码实现比较简单,下面会给出源码,这里不再涉及。

下面重点看看安卓的代码实现:

这是主的布局代码:activity_listview.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/lv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

这是ListView的子项布局代码:activity_listview_item.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/userNo"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:layout_weight="3"
        android:textSize="15pt" />

    <TextView
        android:id="@+id/userName"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:layout_weight="6"
        android:paddingLeft="13dp"
        android:textColor="#ff0000"
        android:textSize="15pt" />

</LinearLayout>

下面先来理解Adapter:MyListViewAdapter


package com.azer.shop.listviewtest.adapter;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.azer.shop.listviewtest.R;
import com.azer.shop.listviewtest.bean.UserBean;

/**
 * 设置ListView中每一个子项的布局及其内容显示
 * 
 * @author fiver_
 *
 */
public class MyListViewAdapter extends BaseAdapter
{
	@SuppressWarnings("unused")
	//上下文对象
	private Context context;			

	private List<UserBean> userBeanList;
	private LayoutInflater layoutInflater;
	
	public MyListViewAdapter(Context context, List<UserBean> userBeanList)
	{
		this.context = context;
		this.userBeanList = userBeanList;
		layoutInflater = LayoutInflater.from(context);
	}
	
	
	@Override
	public int getCount()
	{
		return userBeanList.size();
	}

	@Override
	public Object getItem(int position)
	{
		return userBeanList.get(position);
	}

	@Override
	public long getItemId(int position)
	{
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent)
	{
		Holder hold;
		
		//降低手机的内存开销
		if (convertView == null || convertView.getTag() == null)
		{
			//加载ListView中每一个子项的布局,
			//因为ListView是有许多相同的模块组成的,activity_listview_item布局就是子模块,由它组成了ListView视图
			convertView = layoutInflater.inflate(R.layout.activity_listview_item, null);

			hold = new Holder();
			hold.userNo = (TextView) convertView.findViewById(R.id.userNo);
			hold.userName = (TextView) convertView.findViewById(R.id.userName);

			convertView.setTag(hold);
		} 
		else
		{
			hold = (Holder) convertView.getTag();
		}


		UserBean userBean = userBeanList.get(position);
		
		
		hold.userNo.setText(userBean.getUserNo());
		hold.userName.setText(userBean.getUserName());

		return convertView;

	}
	
	/**
	 * 封装item布局中的控件,也体现了面向对象的思想
	 * 
	 * @author fiver_
	 *
	 */
	private static class Holder
	{
		private TextView userNo;
		private TextView userName;
	}
}

上面的注释写得比较清楚,这个类的作用就是一个适配器的作用,它是数据与ListView的中间桥梁,可以想象电脑的电源适配器,就应该理解了。它负责处理的是组成ListView的每一个子项布局。


再来看看Activity组件的实现:MainActivity



package com.azer.shop.listviewtest.activity;

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

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.Toast;

import com.azer.shop.listviewtest.R;
import com.azer.shop.listviewtest.adapter.MyListViewAdapter;
import com.azer.shop.listviewtest.bean.UserBean;
import com.azer.shop.listviewtest.config.UriAddress;
import com.azer.shop.listviewtest.fastjson.UserBeanJSon;
import com.azer.shop.listviewtest.utils.DataNetworkUtil;

/**
 * 安卓listView的使用及与服务器通信相关的操作
 * 
 * @author fiver_
 * @since 2015-04-27
 * 
 */
public class MainActivity extends Activity
{
	//ListView视图组件
	private ListView listView;
	
	//自定义Adapter数据适配器
	private MyListViewAdapter myListViewAdapter;
	
	//用于存放从网络上获取的值
	private List<UserBean> userBeanList;

	//判断网络的连接状态,默认是false,表示不通
	private boolean judgeResultIsNull;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_listview);
		
		findViewById();
		
		initData();
	}
	
	/**
	 * 初始化控件
	 * 
	 */
	private void findViewById()
	{
		listView = (ListView) findViewById(R.id.lv);
	}
	
	private void initData()
	{
		//访问网络
		new Thread(runnable).start();
	}

	
	//网络线程,通过地址访问后台获取后台的数据
	Runnable runnable = new Runnable()
	{
		@Override
		public void run()
		{ 
			//用于存放向后台发送的数据,以键值对的形式
			Map<String, String> params = new HashMap<String, String>();
			
			//传一些参数给后台
			params.put("userId", "sa");
			
			String result = "";
			
			try
			{
				byte[] b = DataNetworkUtil.getUri(UriAddress.NAMESPACE + UriAddress.GETINFO, params);

				if (b != null)
				{
					result = new String(b);
					judgeResultIsNull = true;
				}
				else
				{
					//网络连接不通
					judgeResultIsNull = false;
				}
			} 
			catch (Exception e)
			{
				e.printStackTrace();
			}
			
			userBeanList = UserBeanJSon.getuserBean(result);
			
			//从网络线程回归到主线程,来修改activity中的布局内容
			runOnUiThread(new Runnable()
			{
				@Override
				public void run()
				{
					if(userBeanList!=null && userBeanList.size()>0)
					{
						//将获取到的数据通过构造函数填充到适配器中
						myListViewAdapter = new MyListViewAdapter(MainActivity.this, userBeanList);
						
						//将适配器与ListView视图进行适配填充
						listView.setAdapter(myListViewAdapter);
					}
					else if(judgeResultIsNull == false)
					{
						Toast.makeText(MainActivity.this, "网络连接异常!!", Toast.LENGTH_LONG).show();
					}
					else
					{
						Toast.makeText(MainActivity.this, "没有相关的用户信息!!", Toast.LENGTH_LONG).show();
					}
				}
			});			
		}
	};
}


该类中主要用到了网络的访问,使用的是Runnable对象。在安卓4.0及以后的版本中,禁止在主线程(UI)线程中直接访问网络uo,必须通过子线程才能访问网络。具体的网络连接实现如下所示:DataNetworkUtil


package com.azer.shop.listviewtest.utils;

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

public class DataNetworkUtil
{
	@SuppressWarnings("unused")
	private static String URL_ENCODER = "UTF_8";	//"GBK";

	public static byte[] getUri(String uri, Map<String, String> params) throws ClientProtocolException, IOException
	{

		byte[] result = null;

		StringBuilder sb = new StringBuilder();
		sb.append(uri);

		if (null != params && params.size() != 0)
		{
			sb.append("?");
			for (Entry<String, String> entry : params.entrySet())
			{
				sb.append(entry.getKey()).append("=").append(entry.getValue());
				sb.append("&");
			}
			sb.deleteCharAt(sb.length() - 1);
		}

		System.out.println("URI ==>> " + sb.toString());
		
		// 创建一个http请求对象
		HttpGet request = new HttpGet(sb.toString());

		// 创建HttpParams以用来设置HTTP参数
		HttpParams pas = new BasicHttpParams();

		HttpClient httpClient = new DefaultHttpClient(pas);
		try
		{
			// 执行请求参数项
			HttpResponse response = httpClient.execute(request);
			
			// 判断请求是否成功
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
			{
				// 获得响应信息
				result = EntityUtils.toByteArray(response.getEntity());
				return result;
			} 
			else
			{
				//服务器连接失败,则返回空;
			}

		} 
		catch (Exception e)
		{
			 e.printStackTrace();
		} 
		finally
		{
			//释放网络连接资源
			httpClient.getConnectionManager().shutdown();
		}
		
		return null;
	}
}

采用的是HttpClient,这个实现比价简单,也可以使Android Api中提供的URLConnection方式。


特别需要注意的是在安卓全局配置文件中需要添加网络访问的权限,以及模拟器的地址是10.0.2.2,而不能使用localhost.


下面给出该源码的下载链接,包括前台安卓和后台的服务器程序。


http://download.csdn.net/detail/u012191462/8638223




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值