Android 应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过 分页的形式来展示数据,
因此,很多应用都是采用分批次加载的形式来获取用户所需的数据。例如:微博客户端可能会在用户滑 动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据。
下面通过一个例子来展示listview下拉自动刷新;数据来源数据库,虽然网上有很多listview下拉刷新的例子;但大多都是使用静态数据,数据库取数据的非常少,今天就花点时间给大家介绍下Android访问数据库的流程,
希望能解开新手的困惑,,因为小弟也是初学者,高手别吐槽,路过就好。
数据库:SQL Server 2008
服务端:Servlet
Android sdk 4.2.2
数据格式:json
先来看下数据库里面的数据;通过分页加载数据库中的 影片类型表,展示部分数据
上面展示的是我数据里面影片类型的部分数据,通过加载数据以json的格式返回给Android客户端;在客户端解析json显示在listview中
服务端项目
关于服务端servlet的代码,贴出来给大家看看;一切都准备好了之后,部署在 Tomcat上面,如果不知道如何部署的话,
可以去我以前写的关于如何部署项目的博客:
int size=Integer.parseInt(req.getParameter("size"));
int index=Integer.parseInt(req.getParameter("index"));
GetAll g=new GetAll();
//返回影片类型对象
List<GoodTypeModel> list=g.getGoodAll(index,size);
int num=g.getGoodTypeCount();
List<HashMap<String, Object>> arraylist=new ArrayList<HashMap<String,Object>>();
JSONObject json=new JSONObject();
if(list!=null)
{
try {
for(int i=0;i<list.size();i++)
{
HashMap<String, Object> map=new HashMap<String, Object>();
map.put("id", list.get(i).getgT_id());
map.put("namg", list.get(i).getgT_Name());
map.put("parent", list.get(i).getgT_ParentID());
arraylist.add(map);
}
//返回json格式的数据
JSONObject json2=new JSONObject();
json2.put("commentlist", arraylist);
json.put("isok", 0);
json.put("num", num);
json.put("data", json2);
out.print(json);
out.close();
} catch (Exception e) {
try {
json.put("isok", 1);
json.put("data", "");
out.print(json);
out.close();
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
上面的代码将一个影片对象转换成 json数据并返回给 客户端
转换之后前 10条json数据
{"num":37,"data":{"commentlist":[{"id":1,"namg":"所有类型","parent":0},{"id":2,"namg":"影视","parent":1},{"id":3,"namg":"音乐","parent":1},{"id":4,"namg":"电影","parent":1},{"id":5,"namg":"内地","parent":2},{"id":6,"namg":"港台","parent":2},{"id":7,"namg":"欧美","parent":2},{"id":8,"namg":"日韩","parent":2},{"id":9,"namg":"动作","parent":2},{"id":10,"namg":"犯罪","parent":2}]},"isok":0}
其中:isok:成功返回的标志,“0”表示成功 “1” 失败返回
num:数据库中表的总记录数
data:影片类型数据总条数
到这里json数据已经准备好了;
下面我们来看看Android客户端
MainActivity的布局文件很简单;就一个listview控件
footer.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:gravity="center"
android:id="@+id/footer_lin"
android:visibility="visible"
android:orientation="horizontal" >
<ProgressBar
android:id="@+id/footer_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleSmall"
/>
<TextView
android:id="@+id/footer_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="@string/footer_more"
/>
</LinearLayout>
listview_item.xm文件也很简单,包括3个TextView控件,代码就不贴出来了;
下面看MainActivity.java代码
private LinearLayout lin;
private ListView listview;
private final static String URL = "http://localhost:8080/listviewManager/getListViewScroll";
private String index = "1"; //默认当前页
private String size="10"; //每页的大小
private int num; //数据总记录数
private View footer; //listview脚部视图
private MyAdapter adapter;
private List<HashMap<String, Object>> datalist = new ArrayList<HashMap<String, Object>>();
private int lastitem=0; //可视最后索引
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lin=(LinearLayout)findViewById(R.id.footer_lin);
footer=getLayoutInflater().inflate(R.layout.footer, null);
listview = (ListView) findViewById(R.id.listview);
listview.setOnScrollListener(scrollListener);
new MyThread().start();
adapter = new MyAdapter(MainActivity.this, datalist);
listview.addFooterView(footer);
listview.setAdapter(adapter);
}
下面代码是通过子线程异步加载json数据
class MyThread extends Thread
{
@Override
public void run() {
String re=getListItem(index,size);
Message msg=new Message();
msg.obj=re;
myHandler.sendMessage(msg);
}
}
private Handler myHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.obj.toString().equals("0"))
{
//通知listview更新数据
adapter.notifyDataSetChanged();
}else if(msg.obj.toString().equals("1"))
{
SyncHttp.showToast(MainActivity.this, "加载数据失败");
}else
{
SyncHttp.showToast(MainActivity.this, "网络异常");
}
}
};
下面是listview的OnScrollListener事件,当listview滑动到最下面的时候,去数据库在取15条数据
/**
* listview滑动事件,滑动到最下面的时候取数据库加载15条数据
* 如果数据已经全部加载完了;移除listview脚部的view
*/
private OnScrollListener scrollListener=new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView arg0, int state) {
if(lastitem==adapter.getCount() && state==OnScrollListener.SCROLL_STATE_IDLE)
{
if(lastitem==num)
{
listview.removeFooterView(footer);
SyncHttp.showToast(MainActivity.this, "全部数据加载完成");
}else
{
index=String.valueOf(Integer.parseInt(index)+1);
Log.i("msg", "index="+index);
new MyThread().start();
adapter.notifyDataSetChanged();
}
Log.i("msg", "onScrollStateChanged--lastitem"+lastitem);
Log.i("msg", "onScrollStateChanged--adapter.getCount"+adapter.getCount());
Log.i("msg", "onScrollStateChanged--num"+num);
}
}
@Override
public void onScroll(AbsListView arg0, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
lastitem=firstVisibleItem+visibleItemCount-1;
Log.i("msg", "lastitem="+lastitem);
}
};
下面的代码是访问网络,(前面写的servlet返回json的方法) 并且返回json数据的方法
/**
* 访问网络并且返回json数据
* @param indexs 当前页
* @param sizes 每页的记录数
* @return 0:返回数据成功 1:获取数据失败 2:异常错误
*/
public String getListItem(String indexs,String sizes)
{
String re="0";
try {
String result= SyncHttp.httpGet(URL, "index="+indexs+"&size="+sizes);
// Log.i("msg", "result="+result);
JSONObject json = new JSONObject(result.toString());
String isok = json.getString("isok");
num = json.getInt("num");
if ("0".equals(isok)) {
JSONObject object = json.getJSONObject("data");
JSONArray array = object.getJSONArray("commentlist");
for (int i = 0; i < array.length(); i++) {
JSONObject obj = (JSONObject) array.opt(i);
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id", obj.getString("id"));
map.put("name", obj.getString("namg"));
map.put("patent", obj.getString("parent"));
datalist.add(map);
}
} else {
//SyncHttp.showToast(MainActivity.this, "获取数据失败");
re="1";
}
} catch (Exception e) {
e.printStackTrace();
re="2";
}
return re;
}
因为我们要访问网络,在AndroidManifest.xml中加上
<uses-permission android:name="android.permission.INTERNET" />
需要注意,不管是模拟器还是 真机测试;URL都要写本地的真是ip地址;否则会出现访问不了网络的情况
本实例模拟器 和真机都测试过,都是可以正常运行的
模拟器测试效果图
到此,Android客户端访问数据库基本已经完成。如果有错误的地方希望 高手指出。