您的位置:首页 > Web前端 > JavaScript

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

2015-04-27 17:03 447 查看
在安卓开发的过程中,网络通信模块必不可少,尤其对于任何一个具有商用价值的应用,都离不开网络通信。今天我来谈谈我对安卓中网络访问、以及常见的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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: