在android系统中使用的是sqlite数据库,前面的简易登录系统已经讲述了数据库的应用。本例的重点是实现数据库与listview的绑定。demo的数据是将个人的信息绑定到listview中,并存在sqlite。
1.person类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class PersonInfo 2 { 3 public PersonInfo() 4 { 5 6 } 7 private String name; 8 private int age; 9 public void setNmae(String name) 10 { 11 this.name=name; 12 } 13 public String getName() 14 { 15 return name; 16 } 17 public int getAge() 18 { 19 return age; 20 } 21 public void setAge(int age) 22 { 23 this.age=age; 24 } 25 }
person类定义了name和age两个属性字段
2.list_item.xml
本例是将person信息绑定到listview中,有必要定义自己的listview项。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <LinearLayout 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:orientation="horizontal" > 11 12 <TextView 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:text="@string/tvname" /> 16 17 <TextView 18 android:id="@+id/tv_name" 19 android:layout_width="match_parent" 20 android:layout_height="wrap_content" /> 21 22 </LinearLayout> 23 24 <LinearLayout 25 android:layout_width="match_parent" 26 android:layout_height="wrap_content" 27 android:orientation="horizontal" > 28 29 <TextView 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" 32 android:text="@string/tvage" /> 33 34 <TextView 35 android:id="@+id/tv_age" 36 android:layout_width="match_parent" 37 android:layout_height="wrap_content" /> 38 39 </LinearLayout> 40 </LinearLayout>
xml文档中定义了几个textview分别用来显示name和age。
3.main.xml
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 tools:context=".MainActivity" > 6 7 <ListView 8 android:id="@+id/listView1" 9 android:layout_width="match_parent" 10 android:layout_height="match_parent" > 11 </ListView> 12 13 </RelativeLayout>
main,xml只有一个listview,用来显示person
4.list_footer
listview可以添加底部或者头部的视图对象。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <Button 8 android:id="@+id/bt_load" 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content" 11 android:text="加载更多数据" /> 12 <ProgressBar 13 android:id="@+id/pg" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:layout_gravity="center_horizontal" 17 android:visibility="gone" 18 /> 19 </LinearLayout>
底部xml只有button,用来加载更多的数据。
5.personinfo.xml
本例的person信息是手动添加到数据库的,并不是在代码中自己生成的数据。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" > 6 7 <LinearLayout 8 android:layout_width="fill_parent" 9 android:layout_height="wrap_content" 10 android:layout_gravity="center" 11 android:orientation="horizontal" > 12 13 <TextView 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:text="@string/tvname" /> 17 18 <EditText 19 android:id="@+id/edname" 20 android:layout_width="match_parent" 21 android:layout_height="wrap_content" /> 22 23 </LinearLayout> 24 25 <LinearLayout 26 android:layout_width="fill_parent" 27 android:layout_height="wrap_content" 28 android:layout_gravity="center" 29 android:layout_weight="0" 30 android:orientation="horizontal" > 31 32 <TextView 33 android:layout_width="wrap_content" 34 android:layout_height="wrap_content" 35 android:text="@string/tvage" /> 36 37 <EditText 38 android:id="@+id/edage" 39 android:layout_width="match_parent" 40 android:layout_height="wrap_content" 41 android:inputType="number" /> 42 43 </LinearLayout> 44 45 </LinearLayout>
xml定义了edittext,写入nanme和age
6.menu.xml
menu是本例的重点,本来是研究menu的使用。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <menu xmlns:android="http://schemas.android.com/apk/res/android" > 2 3 <item android:showAsAction="ifRoom|withText" android:id="@+id/action_add" android:title="@string/action_add"></item> 4 <item android:showAsAction="ifRoom|withText" android:id="@+id/action_delete" android:title="@string/action_delete"></item> 5 <item 6 android:id="@+id/action_settings" 7 android:orderInCategory="100" 8 android:showAsAction="never" 9 android:title="@string/action_settings"/> 10 11 </menu>
本文档定义了几个菜单项,如果运行在3.0以上的android系统中,ui显示方式有很大不同。showasaction用来设置menu的显示方式。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 @Override 2 public boolean onCreateOptionsMenu(Menu menu) { 3 // Inflate the menu; this adds items to the action bar if it is present. 4 getMenuInflater().inflate(R.menu.main, menu); 5 return true; 6 } 7 public boolean onOptionsItemSelected(MenuItem menu) 8 { 9 switch(menu.getItemId()) 10 { 11 case R.id.action_add: 12 addUser(); 13 return true; 14 case R.id.action_delete: 15 //deleteUser(); 16 return true; 17 default: 18 super.onOptionsItemSelected(menu); 19 } 20 return true; 21 }
这段代码是menu的初始化以及对menu菜单项选中事件的监听。
7.contextmenu
本例个人信息的删除是用contextmenu实现的,用户长按lsitview的某一项,即可弹出删除的上下文菜单。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public void onCreateContextMenu(ContextMenu menu,View view,ContextMenuInfo menuInof) 2 3 { 4 super.onCreateContextMenu(menu, view, menuInof); 5 menu.add(0,1,Menu.NONE,"删除"); 6 } 7 public boolean onContextItemSelected(MenuItem item) 8 { 9 switch(item.getItemId()) 10 { 11 case 1: 12 deleteUser(delname); 13 return true; 14 default: 15 return false; 16 } 17 }
registerForContextMenu(listview);菜单注册到某视图。
8.addperson和deleteperson
添加和删除个人信息都与sqlite数据库相关。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 private static final String DATABASE_NAME="test"; 2 public SQLiteHelper(Context context, String name, CursorFactory factory, 3 int version) { 4 super(context, name, factory, version); 5 this.getWritableDatabase(); 6 // TODO Auto-generated constructor stub 7 } 8 9 @Override 10 public void onCreate(SQLiteDatabase db) { 11 // TODO Auto-generated method stub 12 db.execSQL("CREATE TABLE IF NOT EXISTS person"+"(id INTEGER PRIMARY KEY,name VARCHAR,age INTEGER)"); 13 14 } 15 //关闭数据库 16 public void close() 17 { 18 this.getWritableDatabase().close(); 19 } 20 public boolean Addperson(int age,String name) 21 { 22 try 23 { 24 ContentValues cv=new ContentValues(); 25 cv.put("name", name); 26 cv.put("age", age); 27 this.getWritableDatabase().insert("person", null, cv); 28 return true; 29 } 30 catch(Exception ex) 31 { 32 return false; 33 } 34 } 35 @Override 36 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 37 // TODO Auto-generated method stub 38 39 }
sqlhelper类用来数据库和表的创建,同时定义了添加person的方法。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 private void addUser() { 2 // TODO Auto-generated method stub 3 final LinearLayout layout=(LinearLayout)getLayoutInflater().inflate(R.layout.personinfo, null); 4 new AlertDialog.Builder(this).setTitle("添加联系人").setView(layout).setPositiveButton("确定",new OnClickListener() { 5 6 @Override 7 public void onClick(DialogInterface dialog, int which) { 8 // TODO Auto-generated method stub 9 EditText edname=(EditText)layout.findViewById(R.id.edname); 10 EditText edage=(EditText)layout.findViewById(R.id.edage); 11 String sql="select * from person where name=?"; 12 Cursor cursor=sqlhelper.getWritableDatabase().rawQuery(sql, new String[]{edname.getText().toString()}); 13 if(cursor.moveToFirst()) 14 { 15 Toast.makeText(MainActivity.this, "已经存在", Toast.LENGTH_LONG).show(); 16 } 17 else 18 { 19 if(sqlhelper.Addperson(Integer.parseInt(edage.getText().toString()), edname.getText().toString())) 20 { 21 PersonInfo person=new PersonInfo(); 22 person.setNmae(edname.getText().toString()); 23 person.setAge(Integer.parseInt(edage.getText().toString())); 24 list.add(person); 25 adapter.notifyDataSetChanged(); 26 Toast.makeText(MainActivity.this, "信息添加成功", Toast.LENGTH_LONG).show(); 27 } 28 } 29 } 30 }).setNegativeButton("取消", null).show(); 31 }
该段代码实现了个人信息的添加,通过调用AlertDialog实现。点击menu中的添加之后,会弹出添加用户的对话框,点击确定信息将会被保存。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 private void deleteUser(String str) { 2 // TODO Auto-generated method stub 3 try 4 { 5 sqlhelper.getWritableDatabase().delete("person", "name=?", new String[]{str}); 6 for(int i=0;i<list.size();i++) 7 { 8 PersonInfo person=list.get(i); 9 if(person.getName()==str) 10 { 11 list.remove(i); 12 } 13 } 14 adapter.notifyDataSetChanged(); 15 } 16 catch(Exception ex) 17 { 18 Toast.makeText(this, "删除失败", Toast.LENGTH_LONG).show(); 19 } 20 }
个人信息删除调用sqlite的delete方法实现,需要传入表的名称,删除的条件。同时在完成数据的删除后,通知listview数据已经发生变化。本例将读取到的数据存在list中,所以移除了list中的数据。
9.Mybaseadapter
mybaseadapter是listview的适配器,继承与baseadapter。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class MyAdapter extends BaseAdapter 2 { 3 4 int count=5; 5 Context mcontext; 6 public MyAdapter(Context context) 7 { 8 mcontext=context; 9 } 10 @Override 11 public int getCount() { 12 // TODO Auto-generated method stub 13 if(list.size()>5) 14 { 15 return count; 16 } 17 else 18 { 19 return list.size(); 20 } 21 } 22 23 @Override 24 public Object getItem(int arg0) { 25 // TODO Auto-generated method stub 26 return null; 27 } 28 29 @Override 30 public long getItemId(int arg0) { 31 // TODO Auto-generated method stub 32 return 0; 33 } 34 35 @Override 36 public View getView(int arg0, View arg1, ViewGroup arg2) { 37 // TODO Auto-generated method stub 38 PersonInfo person=new PersonInfo(); 39 if(arg1==null) 40 { 41 arg1=LayoutInflater.from(mcontext).inflate(R.layout.person_item, null); 42 } 43 44 person=(PersonInfo)list.get(arg0); 45 46 TextView edname=(TextView)arg1.findViewById(R.id.tv_name); 47 TextView edage=(TextView)arg1.findViewById(R.id.tv_age); 48 edname.setText(person.name); 49 edage.setText(String.valueOf(person.age)); 50 return arg1; 51 } 52 53 }
本例定义每次只能显示5条数据。当小于5条数据的时候,将全部显示。这里设置返回的数目是关键。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 btnpro=(Button)moreview.findViewById(R.id.bt_load); 2 pg=(ProgressBar)moreview.findViewById(R.id.pg); 3 btnpro.setOnClickListener(new View.OnClickListener() { 4 5 @Override 6 public void onClick(View v) { 7 // TODO Auto-generated method stub 8 pg.setVisibility(View.VISIBLE);// 将进度条可见 9 btnpro.setVisibility(View.GONE);// 按钮不可见 10 Handler hanldre=new Handler(); 11 hanldre.postDelayed(new Runnable(){ 12 13 @Override 14 public void run() { 15 // TODO Auto-generated method stub 16 17 adapter.count+=5; 18 19 btnpro.setVisibility(View.VISIBLE); 20 pg.setVisibility(View.GONE); 21 if(adapter.count>list.size()) 22 23 { 24 adapter. count=list.size(); 25 btnpro.setVisibility(View.INVISIBLE); 26 } 27 adapter.notifyDataSetChanged(); 28 }}, 2000); 29 } 30 });
这是加载更多数据按钮的监听事件。代码中新建了hanlder实例,用来加载更多的数据。其中当count大于list.size,count等于list.size.
10.系统退出
在android中,很多系统在用户按返回键的时候,并不是直接退出,而是弹出对话框。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public boolean onKeyDown(int keyCode, KeyEvent event) 2 { 3 if(keyCode==KeyEvent.KEYCODE_BACK && event.getRepeatCount()==0) 4 { 5 new AlertDialog.Builder(this).setTitle("系统提示").setMessage("确定退出系统吗").setPositiveButton("确定", new OnClickListener() { 6 7 @Override 8 public void onClick(DialogInterface dialog, int which) { 9 // TODO Auto-generated method stub 10 android.os.Process.killProcess(android.os.Process.myPid()); 11 } 12 }).setNegativeButton("取消", null).show(); 13 return true; 14 } 15 else if(keyCode==KeyEvent.KEYCODE_MENU && event.getRepeatCount()==0) 16 { 17 openOptionsMenu(); 18 return true; 19 } 20 return true; 21 }
这个功能通过重写onkeydown方法实现。但是实现过程中发现menu菜单不能显示了,所以在这里加了一个判断,并调用了 openOptionsMenu()。
11.系统实例