`
huiqinbo
  • 浏览: 334220 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

无废话Android 系列教程36 -2 [listview的工作原理及使用&测试]

 
阅读更多

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;
	}
	
	

}
 
6.  com.andy.listview1.test 包下的TestPersonListView.java
 
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";
}
 
7.  layout 下的 activity_main.xml
<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>
 
  这段xml代码的效果如下:


 
 
8. 项目部署后的效果:



  

 9. 项目源代码参照附件

 

  • 大小: 137.5 KB
  • 大小: 304.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics