`
huiqinbo
  • 浏览: 344709 次
  • 性别: 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
分享到:
评论

相关推荐

    无废话Android 系列教程36-1 [模仿listview的工作原理&测试]

    在“无废话Android系列教程36-1”中,我们将深入探讨ListView的工作原理,并通过实际的代码测试来加深理解。这篇教程旨在帮助开发者们更高效地使用和优化ListView,提高应用性能。 ListView的核心机制是视图复用...

    Android开发-Retrofit-AndroidStudio(三)ListView&Picasso_免积分

    本教程将探讨如何在Android Studio项目中结合Retrofit和ListView来实现数据展示,并利用Picasso库处理网络图片的加载。以下是详细的知识点介绍: 1. **Retrofit简介** - Retrofit是由Square公司开发的一个Type-...

    Android应用源码之drag-sort-listview-master.rar

    通过研究`drag-sort-listview-master`的源码,开发者不仅可以学习到拖放排序的实现,还可以深入了解Android ListView的工作原理,以及如何优雅地处理触摸事件和视图更新。这对于提升个人的Android开发技能,特别是...

    Android--开发-- ListView下拉刷新 Demo.rar

    在Android应用开发中,ListView是常用的控件,用于展示大量数据列表。然而,为了提供更好的用户体验,许多应用都需要实现ListView的下拉刷新功能,让用户能够即时获取最新的数据。本示例"Android--开发-- ListView...

    Android--开发--ListView 中的item随意拖动.rar

    首先,要实现ListView的拖动功能,我们需要理解ListView的工作原理。ListView通过Adapter来获取并展示数据,每个item视图都是由一个View或ViewHolder对象表示。当用户触摸屏幕并滑动时,我们需要捕获这些触控事件,...

    Android-滑动listview标题置顶listview吸顶效果

    在Android应用开发中,UI设计和用户体验是至关重要的部分,特别是在构建列表视图(ListView)时。本知识点主要探讨如何实现“滑动ListView时标题置顶”和“ListView吸顶效果”,以及如何使安卓系统状态栏透明化。这些...

    android--ListView下拉刷新demo

    在Android开发中,ListView是一种常见的组件,用于展示大量的列表数据。`ListView`的下拉刷新功能是提升用户体验的重要特性,特别是在处理动态加载数据的应用场景中。这个“android--ListView下拉刷新demo”就是一个...

    Android--开发--ListView 实现点击侧边A-Z快速查找.rar

    在Android应用开发中,ListView是常用的视图组件,它用于展示大量的列表数据。这个压缩包文件"Android--开发--ListView 实现点击侧边A-Z快速查找.rar"显然包含了一个示例,展示了如何在ListView中实现点击侧边字母...

    Android代码-Animated-Expanding-ListView

    For more details, visitAnimated-Expanding-ListView Developed by @LeonardoCardoso. Animated Expanding ListView provides a fancy animation on expanding or collapsing the content of a listview item. It...

    Android--开发--ListView上下翻页效果.rar

    首先,我们需要了解ListView的基本工作原理。ListView依赖于Adapter来提供数据,Adapter就像是ListView的数据源,它负责将数据转化为ListView项视图。在Android中,常见的Adapter有ArrayAdapter、SimpleAdapter和...

    android的listview嵌套listview,列表嵌套列表 android studio版本

    本教程将详细讲解如何在Android Studio环境下实现ListView的嵌套,以满足这种复杂布局的需求。 首先,我们需要了解基本的ListView工作原理。ListView通过Adapter来获取并展示数据,Adapter是连接数据源与ListView的...

    一,android开发经典实例系列-----ListView、GridView.doc

    在Android开发中,ListView和GridView是两种非常重要的布局控件,尤其在展示大量数据时,它们提供了高效且可滚动的视图。以下是关于这两个控件及其相关知识点的详细说明: 1. **ListView**: - ListView是Android ...

    android-world-of-listview-android

    总之,ListView是Android开发中不可或缺的一部分,掌握其工作原理和优化技巧对于构建高性能的移动应用至关重要。通过对虚拟化、适配器、项目属性、标头与脚注、列表选择器等知识点的深入理解,开发者可以充分利用...

    MVVMDemo---listView的使用.rar

    在Android开发中,MVVM(Model-View-ViewModel)架构是一种流行的设计模式,它将业务逻辑、用户界面和数据模型分离,提高了代码的可测试性和可维护性。本示例"MVVMDemo---listView的使用"着重展示了在MVVM架构下如何...

    Android-react-native-timeline-listview.zip

    Android-react-native-timeline-listview.zip,React本机应用程序的时间线组件,安卓系统是谷歌在2008年设计和制造的。操作系统主要写在爪哇,C和C 的核心组件。它是在linux内核之上构建的,具有安全性优势。

    android-pulltorefresh-listview

    本篇文章将深入探讨该库的工作原理以及如何在项目中集成和自定义`android-pulltorefresh-listview`。 一、`android-pulltorefresh`库简介 `android-pulltorefresh`库由英国开发者Chris Banes创建,它提供了一个可...

    ListView总结---关于ListView的一些分享

    本文将深入解析ListView的工作原理及其使用技巧,结合`ContactListActivity分析.doc`文档,帮助开发者更好地理解和优化ListView。 一、ListView的基本结构 ListView的核心组成部分包括Adapter、View Holder和...

    安卓listview相关相关-Android--ListView返回第一条数据的实现.rar

    首先,ListView的工作原理基于Adapter模式,它将数据源(如ArrayList)与视图(ListView中的每个Item)进行绑定。当ListView滚动时,为了优化性能,只渲染可视区域内的View,并复用那些已滑出可视范围的View。这就...

Global site tag (gtag.js) - Google Analytics