1. listview 工作原理: 先需要定义一个线性布局,布局里面只保留屏幕内可显示条数的View 对象
(的引 用),当在屏幕向上拖动一个条目(数据)时,它就移除最上面的View 对象, 将它丢掉。
当在屏幕向下拖动一个条目(数据)时,它就新new出一个View对象,将它显示到页面(屏幕)上。
这样就不需要new 出50/100W个view对象!只需要new出屏幕内能最多显示对象的数目就可以了,如:
屏幕只能最多显示9条数据,这样就需要new出9个View对象即可!
注: 如果使用[模仿listview]的方法来显示5000条数据还没有问题,当数据库里有100W条记录需要显示时,
就需要在LinearLayout线性布局里面 new 出100W个TextView ,这样肯定不行的,系统会崩溃!
所以此时listview 就是绝佳的选择!
2. listview实现模式: 典型MVC模式
M mode 数据模型 获取的List<Person> 集合
V view 视图 listview 对象
C controller 控制器 实现Listadapter接口或继承BaseAdapter抽象类 ( 数据适配器)
3. com.andy.listview1 包下类
MainActivity.java
package com.andy.listview1;
import java.util.List;
import com.andy.listview1.R;
import android.app.Activity;
import android.content.res.ColorStateList;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.andy.listview1.dao.PersonDao2;
import com.andy.listview1.domain.Person;
/**
* 这是一个模仿listview 的类
* @author huiqinbo
*
*/
public class MainActivity extends Activity {
private ListView lv;
private List<Person> persons;
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PersonDao2 dao = new PersonDao2(this);
persons = dao.findAllPerson();
lv = (ListView)findViewById(R.id.lv);
lv.setAdapter(new MyAdapter());
}
// private class MyAdapter implements ListAdapter{
//
// @Override
// public void registerDataSetObserver(DataSetObserver observer) {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public void unregisterDataSetObserver(DataSetObserver observer) {
// // TODO Auto-generated method stub
//
// }
//
// /**
// *
// * listview里面总共有多个条目
// *
// */
// @Override
// public int getCount() {
// // TODO Auto-generated method stub
// int size = persons.size();
// return size;
// }
//
// @Override
// public Object getItem(int position) {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public long getItemId(int position) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// @Override
// public boolean hasStableIds() {
// // TODO Auto-generated method stub
// return false;
// }
//
// /**
// * @param position 是
// */
// @Override
// public View getView(int position, View convertView, ViewGroup parent) {
// TextView tv = new TextView(getApplicationContext());
// Person p = persons.get(position);
// tv.setText(p.toString());
// tv.setTextColor(Color.GREEN);
// tv.setTextSize(10);
// return tv;
// }
//
// @Override
// public int getItemViewType(int position) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// @Override
// public int getViewTypeCount() {
// // TODO Auto-generated method stub
// return 0;
// }
//
// @Override
// public boolean isEmpty() {
// // TODO Auto-generated method stub
// return false;
// }
//
// @Override
// public boolean areAllItemsEnabled() {
// // TODO Auto-generated method stub
// return false;
// }
//
// @Override
// public boolean isEnabled(int position) {
// // TODO Auto-generated method stub
// return false;
// }
//
// }
private class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return persons.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
/**
* 这个方法是:展现屏幕指定位置的数据,(展现数据集合某一位置所对应的数据); 初次打开时 创建屏幕内所容纳数量的view对象,并将它显示出来了
* *特别提示:初次打开时位置是从0开始 至 屏幕所能显示条目的数量!如0-8条,等向上或向下滚动时都是在这8条减少或增加!
* @param position 当前数据在集合中的位置
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.i(TAG, "返回View对象,位置:"+position);
TextView tv = new TextView(getApplicationContext());
//得到某个位置对应的person数据
Person p = persons.get(position);
tv.setText(p.toString());
tv.setTextColor(Color.BLACK);
tv.setTextSize(13);
return tv;
}
}
}
PersonSQLiteOpenHelper.java
package com.andy.listview1;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
* 创建PersonSQLiteOpenHelper类 继承SQLiteOpenHelper抽象类,此时必须创建构造方法
* @author huiqinbo
*
*/
public class PersonSQLiteOpenHelper extends SQLiteOpenHelper {
//通过getSimpleName()方法获取到值为"PersonSQLiteOpenHelper"
private static final String tag = PersonSQLiteOpenHelper.class.getSimpleName();
/**
* 数据库的构造方法, 用来定义数据库的名称/数据库的查询结果集/数据库的版本号
*
* 当版本号发生变化时才可以调用onUpgrade方法; 如版本号从1 →2
* @param context
* @param name
* @param factory
* @param version
*/
public PersonSQLiteOpenHelper(Context context) {
// super(context, "person.db", null, 1);
super(context, "person.db", null, 4);
// TODO Auto-generated constructor stub
}
/**
* 数据库第一次被创建的时候调用的方法
* @param db 被创建的数据库
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table person (id integer primary key autoincrement, name varchar(20), number varchar(20))");
}
/**
* sqlite中ALTER TABLE语句不支持DROP COLUMN,只有RENAME 和ADD 语句.
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
Log.i(tag, "数据库的版本发生变化了");
db.execSQL("alter table person add account varchar(20)");
}
}
4. com.andy.listview1.dao
package com.andy.listview1.dao;
import java.util.ArrayList;
import java.util.List;
import com.andy.listview1.PersonSQLiteOpenHelper;
import com.andy.listview1.domain.Person;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class PersonDao2 {
private PersonSQLiteOpenHelper helper;
public PersonDao2(Context context){
helper = new PersonSQLiteOpenHelper(context);
}
/*
* 插入用户名和手机号到SQLite数据库
*
* the row ID of the newly inserted row, or -1 if an error occurred
*/
public long addPerson(String name, String number,int account){
//此时就获取到了数据库
SQLiteDatabase db = helper.getWritableDatabase();
//db.execSQL("insert into person (name,number) values (?,?)", new Object[]{name,number});
ContentValues values = new ContentValues();
values.put("name", name);
values.put("number", number);
values.put("account", account);
long row_id = db.insert("person", null, values);
db.close();
return row_id;
}
/**
* 删除一条数据,按用户名的条件
* @param name
*
* WhereClause :the optional WHERE clause to apply when deleting. Passing null will delete all rows.
*/
public int deletePerson(String name){
SQLiteDatabase db = helper.getWritableDatabase();
// db.execSQL("delete from person where name =?", new Object[]{name});
int row_id = db.delete("person", "name=?", new String[]{name});
db.close();
return row_id;
}
/**
* 修改一条数据,按用户名的条件
* @param name
* @param number
*/
public int updatePerson(String name, String number){
SQLiteDatabase db = helper.getWritableDatabase();
// db.execSQL("update person set number = ? where name = ?", new Object[]{name,number} );
ContentValues values = new ContentValues();
values.put("number", number);
int row_id = db.update("person", values, "name=?", new String[]{name});
db.close();
return row_id;
}
/**
* 查询一条数据,按用户名的条件
* @param name
* @param number
* selection : A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
* selectionArgs: You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
*/
public boolean findPerson(String name){
SQLiteDatabase db = helper.getWritableDatabase();
// Cursor cursor = db.rawQuery("select * from person where name=?", new String[]{name});
Cursor cursor = db.query("person", new String[]{"id", "name", "number"}, "name=?", new String[]{name}, null, null, null);
boolean result = cursor.moveToNext();
cursor.close();
db.close();
return result;
}
public List<Person> findAllPerson(){
SQLiteDatabase db = helper.getWritableDatabase();
// Cursor cursor = db.rawQuery("select * from person", null);
Cursor cursor = db.query("person", new String[]{"id","name","number"}, null, null, null, null, null);
List<Person> persons = new ArrayList<Person>();
Person person;
while(cursor.moveToNext()){
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String number = cursor.getString(cursor.getColumnIndex("number"));
person = new Person(id,name,number);
persons.add(person);
}
cursor.close();
db.close();
return persons;
}
}
5. com.andy.listview1.domain 包下的Person.ajva
package com.andy.listview1.domain;
public class Person {
private int id;
private String name;
private String number;
public Person(int id, String name, String number){
this.id = id;
this.name= name;
this.number = number;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", number=" + number
+ "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
package com.andy.listview1.test;
import java.util.List;
import java.util.Random;
import com.andy.listview1.PersonSQLiteOpenHelper;
import com.andy.listview1.dao.PersonDao2;
import com.andy.listview1.domain.Person;
import android.database.sqlite.SQLiteDatabase;
import android.test.AndroidTestCase;
import android.util.Log;
/**
*
* @author huiqinbo
*
*/
public class TestPersonListView extends AndroidTestCase {
private static final String tag = TestPersonListView.class.getSimpleName();
public PersonDao2 pd;
/**
* getContext() 是测试框架给提供的上下文件 来源:android.test.AndroidTestCase.getContext()
*
* 第一次执行时调用PersonSQLiteOpenHelper.java 内的onCreate方法,
* 当版本号发生变化时,会调用PersonSQLiteOpenHelper.java 内的onUpgrade方法.
*/
public void testCreatePersonDb() {
PersonSQLiteOpenHelper db = new PersonSQLiteOpenHelper(getContext());
// 打开或创建一个可写的数据库
db.getWritableDatabase();
}
public void testAddPerson() {
pd = new PersonDao2(getContext());
Random random = new Random();
for(int i=0; i<50; i++){
pd.addPerson("ZhangSan"+i, "138001380"+i, random.nextInt(10000));
}
}
//注:查询数据表的结构SQL语句:
//select * from sqlite_master where type="table" and name="person";
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.andy.listview1.MainActivity"
tools:ignore="MergeRootFrame" >
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
9. 项目源代码参照附件