Android SQLite与ListView的简单使用

2017-04-25

初写博客有很多地方都有不足,希望各位大神给点建议。

  回归主题,这次简单的给大家介绍一下Android SQLite与ListView的简单使用sqlite在上节中有介绍,所以在这里废话不多说了,重点说一下listview的使用及优化

listView的概述:

 在 Android 应用开发中,ListView 是最为常见的组件之一。它将数据以列表的形式展现出来,在我们平时的开发中也是很常见。一般而言,一个ListView 由以下三个元素组成:

①View:用来展示列表的 View,通常是一个 XML 文件所指定的。

②适配器:用来把数据映射到 ListView 上,可以理解为 ListView 界面和数据之间的纽带和桥梁。

③数据:具体被映射的数据和资源,可以是字符串、图片等。

  接下来我们简单介绍一下 ListView 加载数据的原理。有了这方面的了解后再说优化才行。ListView 针对每个 item(列表项)都要求 adapter(适配器)“返回一个视图”(getView)。 ListView 在开始绘制的时候系统会首先调用 getCount()函数,根据它的返回值得到 ListView 的长度,然后根据这个长度,逐次调用 getView()方法一行一行的绘制ListView 的每一项。getCount()方法的返回值是几就显示几行。 具体怎么绘制呢?当我们调用 getView()方法时首先会通过加载布局文件生成一个新的 View 对象(实际上是一 个 ViewGroup),然后通过该对象将布局文件中的各个组件实例化(也就是 findViewById()), 这样便可将数据对应到各个组件上了。但是加载布局文件属于 I/O 操作,是很耗时的,当我们的数据量非常庞大或者列表项非常多的时候,很容易导致 ANR(应用程序无响应)现象。

  1.listview的优化方案之__复用历史缓存

所谓的复用,就是循环反复的利用。假如说我们有一百条列表项,我们没有必要一一为他们创建新的对象,我们只要创建三个或者五个 item 对象,之后对他们循环利用即可。 其实 Android 系统本身为我们考虑了 ListView 的优化问题。在 getView()方法中系统就为我们提供了一个复用 View 的历史缓存对象 convertView,当显示第一屏的时候,每一个 item都会新创建一个 View 对象,这些 View 都是可以被复用的。 此时 convertView 在 getView()中是空值。假如说是 item1 滚动出屏幕时会进入到一个叫 Recycler 的 Android构件中去填充 convertView 并缓存起来,当新的项目从屏幕底端上来时,ListView 调用getView()方法,convertView 此时不是空值了,它的值是 item1。 你只需要设置新的数据,然后返回 convertView,不必重新创建一个视图

  2.istview的优化方案之__缓存 item 条目的引用—ViewHolder

findViewById()这个方法是比较耗性能的操作。当我们通过加载布局文件来创建 View 对象的时候,一但该对象生成,其布局文件中子控件的 id 也就不会改变了,因此我们在第一次加载的时候,需要将把相关的数据保存起来,下次直接从缓存中读取,从而减少findViewById()的次数,优化显示效率。

①创建一个静态ViewHolder 内部类(可以抽取)

②创建自定义的类 ViewHolder holder = null ;

③setTag: 在创建新的 ListView 的时候创建新的 ViewHolder 对象,然后通过 findViewById找到子控件并将其引用保存起来。而 View 中有一个方法 setTag,可用来保存一些数据结构。通过 convertView.setTag(holder)将 ViewHolder 对象的引用设置到 view 中。

④在复用 ListView 中条目的时候,再通过 convertView.getTag(holder)获取 holder对象的引用,此时我们只需要去修改其对象中子控件的值即可,不用 findViewById()

先看一下实现的一个界面:

Android SQLite与ListView的简单使用

 项目结构:

Android SQLite与ListView的简单使用

主要代码:MainPage

 package com.hb.system.activity;

 import java.util.List;

 import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.Toast; import com.example.studentinformationsystem.R;
import com.hb.bean.Student;
import com.hb.dao.SqlDao; public class MainPage extends Activity implements OnCheckedChangeListener {
private EditText et_name;
private Button bt_add;
private String name;
private RadioGroup rg_group;
private TextView tv_showsex;
private String showsex;
private SqlDao dao;
private Student stu;
private Student stu2;
private List<Student> list;
private MyAdapter adapter;
private ListView listView1;
private PopupWindow pw;
private TextView delete; @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.mainpage);
initView();
initDate(); }
//初始化视图
private void initView() {
et_name=(EditText) findViewById(R.id.et_name);
bt_add=(Button) findViewById(R.id.bt_add);
rg_group=(RadioGroup) findViewById(R.id.rg_group);
tv_showsex=(TextView) findViewById(R.id.tv_showsex);
listView1=(ListView) findViewById(R.id.listView1);
}
//初始化数据
private void initDate() {
dao=new SqlDao(MainPage.this);
list=dao.findAll();
adapter=new MyAdapter();
listView1.setAdapter(adapter);
rg_group.setOnCheckedChangeListener(this);
bt_add.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
name = et_name.getText().toString().trim();
showsex = tv_showsex.getText().toString().trim();
stu=new Student(name,showsex); if(TextUtils.isEmpty(name) || TextUtils.isEmpty(showsex)){
Toast.makeText(MainPage.this, "添加信息不能为空", Toast.LENGTH_LONG).show(); }else{
stu2=new Student(name);
Student findName = dao.findName(stu2);
if(name.equals(findName.getName())){
Toast.makeText(MainPage.this, "添加的姓名不能一样!", Toast.LENGTH_SHORT).show(); }else{
boolean add = dao.add(stu);
if(add){
list=dao.findAll();
adapter.notifyDataSetInvalidated();
Toast.makeText(MainPage.this, "添加成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainPage.this, "添加失败", Toast.LENGTH_SHORT).show();
}
}
}
}
});
/**
* listview的条目点击事件
*/
listView1.setOnItemClickListener(new OnItemClickListener() {
private String na; @Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
na = list.get(position).getName();
View v = View.inflate(MainPage.this, R.layout.adapter_popu_window, null);
if (pw != null) {
pw.dismiss();//让弹出的PopupWindow消失
pw = null;
}
pw = new PopupWindow(v, -2, -2);
int [] location=new int[2];
view.getLocationInWindow(location);
pw.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
pw.showAtLocation(parent,Gravity.RIGHT+ Gravity.TOP, 20,location[1]-5 );//设置显示的位置
ScaleAnimation animation = new ScaleAnimation(0.3f, 1f, 0.3f, 1f, Animation.RELATIVE_TO_SELF,
Animation.RELATIVE_TO_SELF);//弹出的动画
animation.setDuration(400);//设置动画时间
v.startAnimation(animation);//开启动画
delete = (TextView)v.findViewById(R.id.tv_delete);
/**
* 删除每一个item上的数据
*/
delete.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
dao.delete(na);
list.remove(position);//移除item的条目
list=dao.findAll();//调用查询所有重新再查找一遍
adapter.notifyDataSetChanged();//更新适配器
}
});
}
}); /**
* listview的滑动监听
* 当鼠标上下滑动的时候让PopupWindow消失
*/
listView1.setOnScrollListener(new OnScrollListener() { @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(pw!=null){
pw.dismiss();
pw=null;
}
}
});
} //按钮组的点击事件
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) { //获取变更后的选中项的ID
int radioButtonId = group.getCheckedRadioButtonId();
RadioButton rb = (RadioButton)MainPage.this.findViewById(radioButtonId);
//更新文本内容,以符合选中项
tv_showsex.setText(rb.getText());
}
class MyAdapter extends BaseAdapter{ private String sex2;
private View view;
private String name2;
@SuppressLint("ViewHolder") @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=null ;//设置静态类使其初始化
if(convertView==null){ holder = new ViewHolder();//创建holder对象
view = View.inflate(MainPage.this, R.layout.item,null ); holder.iv_head = (ImageView) view.findViewById(R.id.iv_head);
holder.tv_name = (TextView) view.findViewById(R.id.tv_n);
holder.tv_sex = (TextView) view.findViewById(R.id.tv_s); view.setTag(holder);//用来保存一些数据结构。
}else{
view=convertView;//复用历史缓存
holder=(ViewHolder) view.getTag(); }
name2 = list.get(position).getName();
sex2 = list.get(position).getSex();
if("男".equals(sex2)){ //区分性别
holder.iv_head.setImageResource(R.drawable.nan);
}else{
holder.iv_head.setImageResource(R.drawable.nv);
}
holder.tv_name.setText(name2);
holder.tv_sex.setText(sex2);
return view;
}
@Override
public int getCount() {
return list.size(); //返回list集合中的数据个数
} @Override
public Object getItem(int position) { return null;
} @Override
public long getItemId(int position) { return 0;
} }
//ViewHolder静态类
static class ViewHolder{
ImageView iv_head;
TextView tv_name;
TextView tv_sex;
} }

  Student

  

 package com.hb.bean;

 public class Student {
private String name;
private String sex;
public Student(){
}
public Student(String name){
this.name = name;
}
public Student(String name, String sex) {
super();
this.name = name;
this.sex = sex;
} public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
} }

sqlDao

 package com.hb.dao;

 import java.util.ArrayList;
import java.util.List; import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import com.hb.bean.Student;
import com.hb.helper.OpenHelper; public class SqlDao { private OpenHelper helper;
public SqlDao(Context context) {
helper=new OpenHelper(context);
}
/**
* 添加
* @param stu
* @return
*/
public boolean add(Student stu){
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", stu.getName().toString());
values.put("sex", stu.getSex().toString());
long insert = db.insert("student", null, values);
db.close();
if(insert !=-1){
return true;
}else{
return false;
}
}
/**
* 删除
* @param name
*/
public void delete(String name){
SQLiteDatabase db = helper.getWritableDatabase();
// db.execSQL("delete student where name =?",new String[]{name});
db.delete("student", "name=?", new String[]{name});
db.close();
}
/**
* 修改
* @param name
* @param newsex
*/
public void update(String name, String newsex){
SQLiteDatabase db = helper.getWritableDatabase();
db.execSQL("update student set sex=? where name=?",new Object[]{name,newsex});
db.close();
}
/**
*查找学生姓名
* @param stu
* @return
*/
public Student findName(Student stu2 ){
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from student where name=?", new String[]{stu2.getName()});
Student s = new Student();
while(cursor.moveToNext()){
// String name = cursor.getString(1);
s.setName(stu2.getName());
}
cursor.close();
db.close();
return s;
}
//查询所有学生
public List<Student> findAll(){
SQLiteDatabase db = helper.getReadableDatabase();
List<Student> list =new ArrayList<Student>();
Cursor cursor = db.query("student", null, null, null, null, null, null);
while(cursor.moveToNext()){
//创建学生对象
Student s = new Student();
String name = cursor.getString(1);
String sex = cursor.getString(2);
//添加到学生bean里面
s.setName(name);
s.setSex(sex);
list.add(s);
}
db.close();
cursor.close();
return list; }
}

OpenHelper

 package com.hb.helper;

 import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; public class OpenHelper extends SQLiteOpenHelper { public OpenHelper(Context context) {
super(context, "db.student", null, 1);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table student (_id integer primary key autoincrement,name varchar(20),sex varchar(3))");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }

MainActivity

 package com.hb.system.activity;

 import com.example.studentinformationsystem.R;

 import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends Activity {
private Button bt_login;
private EditText et_name;
private EditText et_pw;
private String name;
private String pw;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); bt_login=(Button) findViewById(R.id.bt_login);
et_name=(EditText) findViewById(R.id.et_name);
et_pw=(EditText) findViewById(R.id.et_pw); bt_login.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
name = et_name.getText().toString().trim();
pw = et_pw.getText().toString().trim();
if(("123").equals(name) && ("123").equals(pw)){
startActivity(new Intent(MainActivity.this, MainPage.class));
}else{
Toast.makeText(MainActivity.this, "密码或账号错误!", Toast.LENGTH_SHORT).show();
}
}
});
}
}

下面的是一些布局代码

activity_main.xml

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp" > <ImageView
android:id="@+id/iv_head"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:background="@drawable/head" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="學号 :"
android:textSize="25sp" /> <EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <TextView
android:id="@+id/tv_pw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码 :"
android:textSize="25sp" /> <EditText
android:id="@+id/et_pw"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:textSize="20sp" />
</LinearLayout> <Button
android:id="@+id/bt_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="50dp"
android:text="登录" /> </LinearLayout>

adapter_popu_window.xml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/local_popup_bg"
android:gravity="center_vertical"
android:orientation="horizontal" > <TextView
android:id="@+id/tv_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除"
android:textColor="@android:color/holo_red_light"
android:textSize="15dip" /> </LinearLayout>

item.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:orientation="horizontal"
android:padding="10dp"
android:gravity="center"> <ImageView
android:layout_gravity="center"
android:id="@+id/iv_head"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_weight="1"
/> <TextView android:id="@+id/tv_n"
android:layout_weight="1"
android:layout_width="0dp"
android:textSize="25dp"
android:layout_height="wrap_content"
android:text="张三"
/> <TextView
android:gravity="center"
android:id="@+id/tv_s"
android:layout_weight="1"
android:layout_width="0dp"
android:textSize="25dp"
android:layout_height="wrap_content"
android:text="男"
/> </LinearLayout>

mainpage.xml

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android1="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:orientation="horizontal" > <TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名 :"
android:textSize="25sp" /> <EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android1:layout_marginTop="25dp"
android:gravity="center"
android1:orientation="horizontal" > <TextView
android1:id="@+id/tv_sex"
android1:layout_width="0dp"
android1:layout_height="wrap_content"
android1:layout_weight="1"
android1:text="性别 :"
android1:textSize="25sp" /> <RadioGroup
android1:id="@+id/rg_group"
android1:layout_width="0dp"
android1:layout_height="wrap_content"
android1:layout_weight="1"
android:gravity="center"
android1:orientation="horizontal" > <RadioButton
android1:id="@+id/boy"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:checked="true"
android1:text="男" /> <RadioButton
android1:id="@+id/girl"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:text="女" />
</RadioGroup> <TextView
android1:id="@+id/tv_showsex"
android1:layout_width="0dp"
android1:layout_height="wrap_content"
android1:layout_weight="1"
android:gravity="center"
android1:text="男" />
</LinearLayout> <Button
android1:id="@+id/bt_add"
android1:layout_width="fill_parent"
android1:layout_height="wrap_content"
android1:layout_marginTop="20dp"
android1:text="增 加" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" > <TextView
android1:id="@+id/stu_head"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:layout_weight="1"
android1:gravity="center"
android1:text="头像"
android1:textSize="25sp" />
<TextView
android1:id="@+id/stu_name"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:layout_weight="1"
android1:gravity="center"
android1:text="姓名"
android1:textSize="25sp" /> <TextView
android:id="@+id/stu_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="性别"
android:textSize="25sp" />
</LinearLayout> <ListView
android1:id="@+id/listView1"
android1:layout_width="match_parent"
android1:layout_height="wrap_content" >
</ListView> </LinearLayout>

项目源码:http://pan.baidu.com/s/1i4ZXUCl

上一篇:Cocos2D中的Framerate状态


下一篇:ThinkPHP中Widget的两种写法及调用