基于SQLiteDatabase的记事本例子

      本例子是用数据库SQLiteDatabase类来存储记事本的数据的,实现了增、删、改、查功能。

      且支持多选删除!

       通过点击listView中的某一项来从数据库中对相应的项进行操作。关键是怎样找到对应的项。以前(最最初接触android时,呵呵。只知道arrayAdapter这个适配器和烂烂的文件存取的情况下,简直是个奇迹~)写的一个记事本例子,是通过listView里的点击位置position:(0、1、2、3、4.......)对应了文件名:(0、1、2、3、4.......)来对相应的文件进行读取,修改,新建,删除。

       但是那种方式有很明显的局限性:当中间一个文件删除后,listView中的条目位置position与文件的编号就会错乱。比如原来是位置在4的条目,由于它上面的一条删除后,它的位置就变为3了。但是它真正对应得文件名却是4.这样,就不能找到对应的文件了。

        而且每次新建时的编号必须是递增的。用过的编号就不能再次使用了,局限性太大了。虽然当时解决这问题时是删除一个文件后它在listView中的条目只是置为空,而不是删除,这样就能通过点击空条目来对以前删除过的条目进行新记事,但是也不太符合实际。

       在已经接触android近半年后今天,终于在短短的一天时间就写出了当时一个周的记事本。当然用到的东西还很简单,android这条路上还有很多要走。

         本来以为还是用ListView的position对应数据库中的id是个不错的办法,但是遗憾的是,数据库中的id没办法在删除后自动重新排序。可能是还没找到方法吧。我放弃了这种通过位置编号来查找的路径了。

        一番思考后我发现,时间是一条信息的唯一标识。可以利用时间来查询数据库中的某一项啊!

         于是。。。

         这个例子用到了好几个我认为以前不知道的东西。

         listView也不是原来单单的一条字符串了。基于BaseAdapter的条目,里面有两个TextView一个checkBox.

还有在listView中使用checkBox时会出现复用问题。就是如果不做处理的话,当第一条checkbox点击后滑动到下面,你会发现下面一页的listView条目checkbox也会被选中了。很奇怪啊!在慕课网有节课讲解了这种问题的两种解决办法,我这里用了其中一种。


还有一个函数:// 通知adapter更新数据,重新调用getView方法
this.myAdapter.notifyDataSetChanged();

数据变化后更新listView,要调用这个方法。


增:ContentValues values = new ContentValues();
values.put("content", note.getContent());
values.put("time", note.getTime());
db.insert(MainActivity.TABLE_NAME, null, values);

删:db.delete(MainActivity.TABLE_NAME, "time like?",
new String[] { time });

改:ContentValues values = new ContentValues();
values.put("content", note.getContent());
values.put("time", note.getTime());
db.update(MainActivity.TABLE_NAME, values, "time like?", new String [] {tag});

查:Cursor c = db.query(MainActivity.TABLE_NAME, null, null, null, null,
null, null);
if (c != null) {
String[] colums = c.getColumnNames();
while (c.moveToNext()) {
String content = c.getString(c.getColumnIndex("content"));
String time = c.getString(c.getColumnIndex("time"));
Note note = new Note(content, time);
notes.add(note);
}
}

包括两个界面,listView展示记事列表界面和书写保存界面。

对界面这次用到了:自定义xml背景,button的按下改变背景色,对button添加自定义style等方法。

activity_main.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >


    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:dividerHeight="1dp"
        android:padding="5dp" >
    </ListView>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ECECEC"
        android:orientation="horizontal"
        android:paddingBottom="10dp"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:paddingTop="10dp" >


        <Button
            android:id="@+id/btn_new"
            style="@style/btn_sytle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="newNote"
            android:text="新建记事" />


        <Button
            android:id="@+id/btn_delete"
            style="@style/btn_sytle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="deleteNote"
            android:text="多选删除" />
    </LinearLayout>


</LinearLayout>


write_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:padding="5dp"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/tv_save_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="00:00"
        android:textColor="#8484FF"
        />
<EditText 
    android:id="@+id/et_content"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:textColor="#0000FF"
    android:textSize="18sp"
    android:paddingTop="20dp"
    android:paddingBottom="20dp"
    android:paddingLeft="5dp"
    android:paddingRight="5dp"
    android:layout_marginBottom="10dp"
    android:gravity="left"
    android:hint="请写下记事"
    
    />
<Button 
  android:layout_marginTop="10dp"
  android:layout_marginBottom="10dp"
  android:layout_marginLeft="5dp"
  android:layout_marginRight="5dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="保存"
    android:textColor="#0000ff"
    android:onClick="save"
    android:background="@drawable/press_btn"
    />
</LinearLayout>


list_item_view.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="5dp" >


    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
          android:layout_alignParentTop="true"
        android:ellipsize="end"
        android:gravity="left"
        android:singleLine="true"
        android:text="金坛哈吉积极啊加啊加点击纠结啊是点击纠结啊是"
        android:layout_marginRight="30dp"
        android:textColor="#0000FF"
        android:textSize="18sp" />


    <CheckBox
        android:id="@+id/check_box"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
      android:layout_alignBottom="@id/tv_title"
        android:layout_alignParentRight="true"
        android:layout_marginRight="1dp"
        android:visibility="visible"
        android:focusable="false"
        android:layout_alignParentTop="true"
       />



    <TextView
        android:id="@+id/tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_below="@id/check_box"
        android:gravity="bottom"
        android:text="12:34"
        android:layout_marginBottom="2dp"
        android:textColor="#8484FF"
        android:textSize="12sp" />


</RelativeLayout>

bg_choosed.xml文件:


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="#66FFFFFF"/>
    <stroke android:width="1dp"
        android:color="#FFFFFF"
        />


</shape>


bg_unchoosed.xml文件:


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle"
    >


    <solid android:color="#00000000" />


    <padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" />


    <stroke
        android:width="2dp"
        android:color="#668484FF" />


</shape>


press_btn.xml文件:


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">


    <item android:drawable="@drawable/bg_choosed" android:state_pressed="true"></item>
    <item android:drawable="@drawable/bg_unchoosed"></item>


</selector>


styles.xml文件中添加:


<style name="btn_sytle">
        <item name="android:layout_width"> 0dp</item>
        <item name="android:layout_height"> wrap_content</item>
        <item name="android:layout_weight">1</item>
        <item name="android:layout_margin">2dp</item>
        <item name="android:textSize">16sp</item>
        <item name="android:background">@drawable/press_btn</item>
        <item name="android:minHeight">0dp</item>
        <item name="android:minWidth">0dp</item>
        <item name="android:textColor">#0000ff</item>
    </style>


java代码部分:

包括两个activity、一个note类、一个dataBaseUtils类

MainActivity.java


package com.fxj.notebook_with_database;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;


import com.fxj.notebook_with_database.data.DataBaseUtils;
import com.fxj.notebook_with_database.data.Note;


public class MainActivity extends ActionBarActivity {
private List<Note> notes;
private ListView listView;


private SQLiteDatabase db;// 数据库
private int deleteFlag = 1;// 第几次点击“多选删除”按钮的标记
public final static String TABLE_NAME = "studb";// 数据库表名
public final static int NEW = 2;// 新建记事的标记
public final static int OLD = 1;// 查看或修改旧记事的标记
boolean visflag = false;// “多选删除”按钮隐藏/显示的标记


private MyAdapter myAdapter;// 适配器


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();


}


private void initData() {
// 创建数据库stu.db
db = openOrCreateDatabase("stu.db", MODE_PRIVATE, null);
// 执行创建表单语句
db.execSQL("create table if not exists "
+ TABLE_NAME
+ "(_id integer primary key autoincrement,content text not null,time text not null)");
if (notes == null) {
// 从数据库中加载数据
notes = DataBaseUtils.getDataFromDatabase(db);
}
myAdapter = new MyAdapter();
listView.setAdapter(myAdapter);// 为ListView设置适配器
// 为list条目添加监听
listView.setOnItemClickListener(new MyListItemClickListener());
}


@Override
protected void onResume() {
refrushView();
super.onResume();
}


private void initView() {
listView = (ListView) findViewById(R.id.list);
}


/**
* 刷新显示页面
*/
public void refrushView() {
notes = DataBaseUtils.getDataFromDatabase(db);
myAdapter.notifyDataSetChanged();
}


/**
* 新建记事

* @param view
*/
public void newNote(View view) {
// 跳转到书写界面
Intent intent = new Intent(MainActivity.this, WriteActivity.class);
intent.putExtra("tag", NEW);// 指明新建记事标记
startActivity(intent);
}


/**
* 删除记事

* @param view
*/
public void deleteNote(View view) {
// 获取删除按钮
Button btnDelete = (Button) findViewById(R.id.btn_delete);
// 如果当前显示的是“多选删除”
if (deleteFlag == 1) {
// 将按钮文字变为“确定删除”
btnDelete.setText("确定删除");
// 改变标记
deleteFlag = 2;
// checkBox显示
visflag = true;
// 通知adapter更新数据,重新调用getView方法
this.myAdapter.notifyDataSetChanged();
} else if (deleteFlag == 2) {// 如果当前显示的是“确定删除”
// 从数据库中删除选中的条目
DataBaseUtils.deleteFromDataBase(db, getSelectItem(notes));
/*
* 此处循环遍历删除不能用for循环, 因为删除自身时,自身的notes.size()也会同时递减,导致不能遍历完全
* 这也是我发现的for循环的一个局限性 for (int i = 0; i < notes.size(); i++) { if
* (notes.get(i).isCheck()) { notes.remove(i); } }
*/
// 从list集合中删除选中的条目
for (Iterator iterator = notes.iterator(); iterator.hasNext();) {
if (((Note) iterator.next()).isCheck()) {
iterator.remove();
}
}
// 将按钮文字变为“多选删除”
btnDelete.setText("多选删除");
// 改变删除按钮标记
deleteFlag = 1;
// checkBox隐藏
visflag = false;
// 通知adapter更新数据,重新调用getView方法
this.myAdapter.notifyDataSetChanged();
}


}


/**
* 找出被选择的条目,添加到被选中项集合

* @param notes
* @return
*/
public List<Note> getSelectItem(List<Note> notes) {
List<Note> selectNotes = new ArrayList<Note>();
for (int i = 0; i < notes.size(); i++) {
if (notes.get(i).isCheck()) {
selectNotes.add(notes.get(i));
}
}
return selectNotes;
}


/**
* 点击条目监听事件

* @author Administrator

*/
private class MyListItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// 获取点击条目上的时间字符串
TextView tvTime = (TextView) view.findViewById(R.id.tv_time);
String time = tvTime.getText().toString();
// 将信息传过去
Intent intent = new Intent(MainActivity.this, WriteActivity.class);
intent.putExtra("tag", OLD);
intent.putExtra("time", time);// 根据时间加载具体的note信息
startActivity(intent);


}


}


private class MyAdapter extends BaseAdapter {


@Override
public int getCount() {
return notes.size();
}


@Override
public Object getItem(int position) {
return notes.get(position);
}


@Override
public long getItemId(int position) {
return position;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
if (convertView == null) {
convertView = LinearLayout.inflate(MainActivity.this,
R.layout.list_item_view, null);
}
// 获取组件
TextView tvTitle = (TextView) convertView
.findViewById(R.id.tv_title);
TextView tvTime = (TextView) convertView.findViewById(R.id.tv_time);
final CheckBox checkBox = (CheckBox) convertView
.findViewById(R.id.check_box);
// 为组件赋值
final Note note = notes.get(pos);
tvTitle.setText(note.getContent());
tvTime.setText(note.getTime());


// 设置checkbox的状态,解决复用的错乱问题
checkBox.setChecked(note.isCheck());
checkBox.setOnClickListener(new android.view.View.OnClickListener(){
@Override
public void onClick(View v) {
note.setCheck(checkBox.isChecked());
}

});



if (visflag) {
checkBox.setVisibility(View.VISIBLE);
} else {
checkBox.setVisibility(View.INVISIBLE);
}
return convertView;
}


}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
} else if (id == R.id.menu_exit) {
exitAlert();
}
return super.onOptionsItemSelected(item);
}


// 退出系统时,弹出提示对话框
public void exitAlert() {
AlertDialog.Builder builder = new Builder(MainActivity.this);
builder.setTitle("温馨提示");
builder.setMessage("确定退出?");
builder.setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
return;
}
});
builder.create().show();
}

//按back键返回时
@Override
public void onBackPressed() {
System.out.println("back---------");
exitAlert();

}
}

WriteActivity.java


package com.fxj.notebook_with_database;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.format.Time;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;


import com.fxj.notebook_with_database.data.DataBaseUtils;
import com.fxj.notebook_with_database.data.Note;


public class WriteActivity extends Activity {
private EditText etContent;

        private TextView tvTime;
private int tag;
private SQLiteDatabase db;
private String time;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去除标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 全屏显示
setContentView(R.layout.write_item);
initView();
initData();


}


private void initData() {
db = openOrCreateDatabase("stu.db", MODE_PRIVATE, null);
db.execSQL("create table if not exists "
+ MainActivity.TABLE_NAME
+ "(_id integer primary key autoincrement,content text not null,time text not null)");
tag = getIntent().getIntExtra("tag", 0);
time = getIntent().getStringExtra("time");
if (tag == MainActivity.NEW)// 新建记事
{
return;
}
// 如果不是新建记事,则加载记事
Note note = DataBaseUtils.getNoteFromDataBase(db, time);
String content = note.getContent();
etContent.setText(content);

                tvTime.setText(time);
etContent.setSelection(content.length());// 设置光标到文字尾
}

private void initView() {
etContent = (EditText) findViewById(R.id.et_content);
                tvTime= (TextView) findViewById(R.id.tv_save_time);           
}

/**
* 保存按钮点击事件

* @param view
*/
public void save(View view) {
// 如果是新建记事的保存
if (tag == MainActivity.NEW) {
if (TextUtils.isEmpty(etContent.getText().toString()))// 如果记事为空,则弹出提示
{
AlertDialog.Builder builder = new Builder(WriteActivity.this);
builder.setTitle("温馨提示");
builder.setMessage("你还没有记事呢!确定退出吗?");
builder.setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.create().show();


} else {
DataBaseUtils.insertNotes(db, getNote());
finish();
}


} else if (tag == MainActivity.OLD)// 如果是对旧记事进行保存
{
// 以时间为标志,更新数据库中的信息
DataBaseUtils.updateNotes(db, getNote(), time);
finish();
}
// finish();
}


public Note getNote() {
// 获取记事内容
String content = etContent.getText().toString();
// 获取保存时间
String time = getCurrentTime();
// 生成note
Note note = new Note(content, time);
return note;
}


public String getCurrentTime() {
String time = "";
Time t = new Time("GMT+8");
t.setToNow();
int month = t.month + 1;
time = t.year + "年" + month + "月" + t.monthDay + "/" + t.hour + ":"
+ t.minute + ":" + t.second;
return time;
}


}


Note.java文件:


package com.fxj.notebook_with_database.data;


public class Note {


private String content;
private String time;
private boolean check;


public boolean isCheck() {
return check;
}


public void setCheck(boolean check) {
this.check = check;
}


public Note(String content, String time) {
super();
this.content = content;
this.time = time;
}


public String getContent() {
return content;
}


public void setContent(String content) {
this.content = content;
}


public String getTime() {
return time;
}


public void setTime(String time) {
this.time = time;
}


@Override
public String toString() {
return "Note [content=" + content + ", time=" + time + "]";
}


}


DataBaseUtils.java文件:


package com.fxj.notebook_with_database.data;


import java.util.ArrayList;
import java.util.List;


import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;


import com.fxj.notebook_with_database.MainActivity;


public class DataBaseUtils {


/**
* 从数据库中获取数据,转化为list对象返回

* @param db
* @return
*/
public static List<Note> getDataFromDatabase(SQLiteDatabase db) {
List<Note> notes = new ArrayList<Note>();
Cursor c = db.query(MainActivity.TABLE_NAME, null, null, null, null,
null, null);
if (c != null) {
String[] colums = c.getColumnNames();
while (c.moveToNext()) {
String content = c.getString(c.getColumnIndex("content"));
String time = c.getString(c.getColumnIndex("time"));
Note note = new Note(content, time);
notes.add(note);


}
}


return notes;
}


/**
* 从数据库中批量删除选中的条目

* @param db
*/
public static void deleteFromDataBase(SQLiteDatabase db,
List<Note> selectNotes) {
// 根据时间标志删除
for (int i = 0; i < selectNotes.size(); i++) {
String time = selectNotes.get(i).getTime();
db.delete(MainActivity.TABLE_NAME, "time like?",
new String[] { time });
System.out.println("删除--->"+time);
}


}
/**
 * //以时间为标志(根据时间找到要更新的note),更新数据库中的信息
 * @param db
 * @param note
 * @param tag
 */
public static void updateNotes(SQLiteDatabase db, Note note,String tag) {
ContentValues values = new ContentValues();
values.put("content", note.getContent());
values.put("time", note.getTime());
db.update(MainActivity.TABLE_NAME, values, "time like?", new String [] {tag});
}
/**
 * 加入新note条目
 * @param db
 * @param note
 */
public static void insertNotes(SQLiteDatabase db, Note note) {
ContentValues values = new ContentValues();
values.put("content", note.getContent());
values.put("time", note.getTime());
db.insert(MainActivity.TABLE_NAME, null, values);
}
/**
 * 根据time 从数据库中获取一个note
 * @param db
 * @param tag
 * @return
 */
public static Note getNoteFromDataBase(SQLiteDatabase db, String tag) {
Note note =null;
Cursor c = db.query(MainActivity.TABLE_NAME, null, "time like?", new String [] {tag}, null, null, null);
if(c!=null)
{
while(c.moveToNext())
{
String content = c.getString(c.getColumnIndex("content"));
String time = c.getString(c.getColumnIndex("time"));
note = new Note(content, time);
}


}
return note;
}
}


运行效果图:










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子林Android

感谢老板,老板大气!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值