android listview下拉刷新(listview 分页),数据来源数据库
Android 应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过 分页的形式来展示数据,
因此,很多应用都是采用分批次加载的形式来获取用户所需的数据。例如:微博客户端可能会在用户滑 动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据。
下面通过一个例子来展示listview下拉自动刷新;数据来源数据库,虽然网上有很多listview下拉刷新的例子;但大多都是使用静态数据,数据库取数据的非常少,今天就花点时间给大家介绍下Android访问数据库的流程,
希望能解开新手的困惑,,因为小弟也是初学者,高手别吐槽,路过就好。
数据库:SQL Server 2008
服务端:Servlet
Android sdk 4.2.2
数据格式:json
先来看下数据库里面的数据;通过分页加载数据库中的 影片类型表,展示部分数据
上面展示的是我数据里面影片类型的部分数据,通过加载数据以json的格式返回给Android客户端;在客户端解析json显示在listview中
服务端项目
关于服务端servlet的代码,贴出来给大家看看;一切都准备好了之后,部署在 Tomcat上面,如果不知道如何部署的话,
可以去我以前写的关于如何部署项目的博客:http://www.cnblogs.com/zhoujian315/p/3165943.html
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客户端访问数据库基本已经完成。如果有错误的地方希望 高手指出。