Android小项目:记事本

前几天写了一个Android记事本小程序,现在记录一下。


项目源码地址在文章最后。


考虑到是记事本小程序,记录的内容只有文字,而且内容不会太长,所以选择使用SQLite数据库,数据存放在用户的手机上。

牵涉到数据库,那自然是一个实体。先设计实体数据表:DBHelper.java

package com.ikok.notepad.DBUtil;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by Anonymous on 2016/3/24.
 */
public class DBHelper extends SQLiteOpenHelper {

    /**
     * 创建笔记表
     */
    private static final String CREATE_NOTE = "create table Note(" +
            "id integer primary key autoincrement," +
            "content text," +
            "time text)";

    private Context mContext;

    public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(CREATE_NOTE);
//        Toast.makeText(mContext,"Created",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

创建完数据表后,自然需要操作数据库,CRUD数据,我把所有跟数据库有关的操作封装在一起: NoteDB.java

package com.ikok.notepad.DBUtil;

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

import com.ikok.notepad.Entity.Note;

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

/**
 * Created by Anonymous on 2016/3/24.
 */
public class NoteDB {

    public static final String DB_NAME = "notepad";
    public static final int VERSION = 1;
    private static NoteDB mNoteDB;
    private SQLiteDatabase db;

    public NoteDB(Context context) {
        DBHelper dbHelper = new DBHelper(context,DB_NAME,null,VERSION);
        db = dbHelper.getWritableDatabase();
    }
    /**
     * 获取 NoteDB 的实例
     * @param context
     * @return
     */
    public synchronized static NoteDB getInstance(Context context){
        if (mNoteDB == null){
            mNoteDB = new NoteDB(context);
        }
        return mNoteDB;
    }

    public void saveNote(Note note){
        if (note != null) {
            ContentValues values = new ContentValues();
            values.put("content", note.getContent());
            values.put("time", note.getTime());
            db.insert("Note", null, values);
        }
    }

    public List<Note> loadNotes(){
        List<Note> noteList = new ArrayList<Note>();
        /**
         * 先按时间降序排列,再按id降序排列
         */
        Cursor cursor = db.query("Note",null,null,null,null,null,"time desc,id desc");
        if (cursor.moveToNext()){
            do {
                Note note = new Note();
                note.setId(cursor.getInt(cursor.getColumnIndex("id")));
                note.setContent(cursor.getString(cursor.getColumnIndex("content")));
                note.setTime(cursor.getString(cursor.getColumnIndex("time")));
                noteList.add(note);
            } while (cursor.moveToNext());
        }
        return noteList;
    }

    public Note loadById(int id){
        Note note = null;
        Cursor cursor = db.query("Note",null,"id = " + id,null,null,null,null);
        if (cursor.moveToNext()){
            note = new Note();
            note.setContent(cursor.getString(cursor.getColumnIndex("content")));
            note.setTime(cursor.getString(cursor.getColumnIndex("time")));
        }
        return note;
    }

    public void deleteById(Integer id){
        db.delete("Note","id = " + id,null);
    }

    public void deleteAllNote(){
        db.delete("Note", null, null);
    }

    public void updateById(String noteTime, String noteContent, int noteId){
        ContentValues values = new ContentValues();
        values.put("content",noteContent);
        values.put("time",noteTime);
        db.update("Note",values,"id = " + noteId,null);
    }

}


设计完数据库后,与数据库对应的需要一个实体类: Note.java

package com.ikok.notepad.Entity;

import java.io.Serializable;

/**
 * Created by Anonymous on 2016/3/24.
 */
public class Note implements Serializable {
    private int id;
    private String content;
    private String time;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

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

接下来进行App主页的设计: main_activity.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:background="@drawable/repeat_bg"
    android:orientation="vertical">

    <TextView
        android:id="@+id/app_title"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:textSize="16sp"
        android:gravity="center"
        android:text="@string/app_title"
        android:textColor="#333"
        />

    <ListView
        android:id="@+id/listview"
        android:descendantFocusability="blocksDescendants"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

    </ListView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        >

        <ImageButton
            android:id="@+id/about_btn"
            android:src="@drawable/about_me"
            android:layout_alignParentLeft="true"
            android:paddingLeft="20dp"
            android:background="#00ffffff"
            android:scaleType="center"
            android:layout_marginTop="4dp"
            android:layout_width="52dp"
            android:layout_height="32dp" />

        <TextView
            android:id="@+id/note_num"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:paddingTop="2dp"
            android:textSize="18sp"
            android:textColor="#333"
            android:layout_centerInParent="true"
            android:text="@string/app_title"
            />

        <ImageButton
            android:id="@+id/write_btn"
            android:src="@drawable/write_btn"
            android:layout_alignParentRight="true"
            android:paddingRight="20dp"
            android:background="#00ffffff"
            android:scaleType="center"
            android:layout_marginTop="4dp"
            android:layout_width="52dp"
            android:layout_height="32dp" />


    </RelativeLayout>


</LinearLayout>


具体效果如下(图标懒得去改颜色了):

左边的是一个关于App的按钮,右边的新建记事本的按钮。


因为主页需要显示已经记录的内容,所以我选择用ListView去显示。用到ListView,则与之对应的是要一个数据源,一个适配器。所以我为每一条子项设计了一个样式,去让它左边显示创建或更新的时间,右边显示内容。如下:list_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:minHeight="50dp"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/show_time"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center"
        android:paddingLeft="10dp"
        android:textColor="#333"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/show_content"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:textSize="16sp"
        android:paddingLeft="20dp"
        android:textColor="#333"
        android:paddingTop="14dp"
        android:singleLine="true" />

</LinearLayout>


创建好了ListView,接下来为它准备适配器:MyAdapter.java

package com.ikok.notepad.Util;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;

import java.util.List;

/**
 * Created by Anonymous on 2016/3/24.
 */
public class MyAdapter extends BaseAdapter {

    private List<Note> noteList;
    private LayoutInflater mInflater;
    private Context mContext;
    private int index;

    public MyAdapter(Context context,List<Note> noteList,ListView listView) {
        this.mInflater = LayoutInflater.from(context);
        this.noteList = noteList;
        this.mContext = context;
    }

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

    @Override
    public Object getItem(int i) {
        return noteList.get(i);
    }

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

    @Override
    public View getView(int i, View convertView, ViewGroup viewGroup) {
        ViewHolder viewHolder = null;
        if (convertView == null){
            viewHolder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.list_item, null);
            viewHolder.mTime = (TextView) convertView.findViewById(R.id.show_time);
            viewHolder.mContent = (TextView) convertView.findViewById(R.id.show_content);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.mTime.setText(noteList.get(i).getTime());
        viewHolder.mContent.setText(noteList.get(i).getContent());

        index = i;

//        convertView.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View view) {
//                Intent intent = new Intent(mContext,UpdateOrReadActivity.class);
                Bundle bundle = new Bundle();
                bundle.putSerializable("note_item",noteList.get(index));
                intent.putExtras(bundle);
//                intent.putExtra("note_id",noteList.get(index).getId());
//                Log.d("Anonymous","备忘录ID:"+noteList.get(index).getId());
//                mContext.startActivity(intent);
//                Log.d("Anonymous","执行了适配器里的点击事件");
//            }
//        });

        return convertView;

    }

    class ViewHolder{
        public TextView mTime;
        public TextView mContent;
    }
}

这里采用了使用ViewHolder,来使ListView滚动的时候不必每次重新创建对象,提升性能。

创建好了ListView,准备好了适配器,接下来要为ListView准备数据源,而这数据源是要从数据库读出来的。但是数据库操作和网络访问等都是属于耗时操作,如果用主UI线程去执行响应操作的话,很可能会出现ANR现象,所以这里我用AsyncTask去执行数据库操作。主Activity代码如下:MainActivity.java

package com.ikok.notepad.Activity;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;

import com.ikok.notepad.DBUtil.NoteDB;
import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;
import com.ikok.notepad.Util.DeleteAsyncTask;
import com.ikok.notepad.Util.MyAdapter;

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

/**
 * Created by Anonymous on 2016/3/24.
 */
public class MainActivity extends Activity {
    /**
     * 布局控件
     */
    private TextView mTitle;
    private TextView mNoteNum;
    private ImageButton mWrite;
    private ListView mNoteListView;
    private ImageButton mAbout;
    /**
     * 数据库实例,数据源
     */
    private List<Note> mNoteList = new ArrayList<Note>() ;
    private NoteDB mNoteDB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main_activity);

        initView();
        new NewAsyncTask().execute();
        initEvent();

    }

    private void initEvent() {
        /**
         * 新写一条备忘录
         */
        mWrite.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, AddNoteActivity.class);
                startActivity(intent);
            }
        });
        /**
         * 修改或查看一条已有的备忘录
         */
        mNoteListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Note note = (Note) adapterView.getItemAtPosition(i);
//                Log.d("Anonymous", "点击ListView获取的note id: " + note.getId());
                Intent intent = new Intent(MainActivity.this, UpdateOrReadActivity.class);
                intent.putExtra("note_id", note.getId());
                startActivity(intent);
            }
        });
        /**
         * listview长按删除
         */
        mNoteListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                final Note note = (Note) parent.getItemAtPosition(position);
//                Log.d("Anonymous", "长按ListView获取的note id: " + note.getId());
                /**
                 * 长按提示是否删除
                 */
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("提示")
                        .setMessage("真的要删除这条记录吗?")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                new DeleteAsyncTask(mNoteDB).execute(note.getId());
                                new NewAsyncTask().execute();
                            }
                        })
                        .setNegativeButton("取消", null)
                        .show();
                return true;
            }
        });
        /**
         * 关于自己
         */
        mAbout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,AboutActivity.class);
                startActivity(intent);
            }
        });

    }

    public void initView() {
        /**
         * 布局控件初始化
         */
        mTitle = (TextView) findViewById(R.id.app_title);
        // 画TextView文字下的下划线
//        mTitle.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);
        mNoteNum = (TextView) findViewById(R.id.note_num);
        mWrite = (ImageButton) findViewById(R.id.write_btn);
        mNoteListView = (ListView) findViewById(R.id.listview);
        mAbout = (ImageButton) findViewById(R.id.about_btn);
        /**
         * 获取数据库实例
         */
        mNoteDB = NoteDB.getInstance(this);
    }
    /**
     * 异步加载备忘录
     */
    class NewAsyncTask extends AsyncTask<Void,Void,List<Note>>{

        @Override
        protected List<Note> doInBackground(Void... voids) {
            mNoteList = mNoteDB.loadNotes();
            return mNoteList;
        }

        @Override
        protected void onPostExecute(List<Note> notes) {
            super.onPostExecute(notes);
            /**
             * 设置适配器,绑定适配器
             */
            MyAdapter myAdapter = new MyAdapter(MainActivity.this,notes,mNoteListView);
            mNoteListView.setAdapter(myAdapter);
            /**
             * 更新备忘录记录数
             */
            int temp = mNoteList.size();
            mNoteNum.setText("共 " + temp + " 条备忘录");
        }
    }
    /**
     * 当活动恢复时,刷新listview和备忘录记录数
     */
    @Override
    protected void onResume() {
        super.onResume();
        new NewAsyncTask().execute();
    }

}

在上面的代码中,我新建了一个 NewAsyncTask 类去继承 AsyncTask,去执行从数据库读取数据的操作,在onPostExecute()方法中,去更新UI,比如显示ListView中的数据,一下页面底部中间有几条数据等。还有我考虑了新建记事本的话,是另外一个Activity。当从另外的Activity返回到主Activity时,主页面应该再刷新一次,刷新数据和显示,所以我在onResume()方法中调用了  NewAsyncTask().execute() 方法,当活动恢复时刷新显示。

接下来是新建记事本的Activity,布局如下:write_note.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/screen_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/repeat_bg"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp">

        <ImageButton
            android:id="@+id/back_btn"
            android:src="@drawable/back_btn"
            android:layout_alignParentLeft="true"
            android:paddingLeft="5dp"
            android:background="#00ffffff"
            android:scaleType="center"
            android:layout_marginTop="6dp"
            android:layout_width="52dp"
            android:layout_height="32dp" />

        <TextView
            android:id="@+id/complete_btn"
            android:layout_alignParentRight="true"
            android:paddingTop="10dp"
            android:paddingRight="10dp"
            android:textSize="18sp"
            android:textColor="#ec6d51"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/complete"/>

    </RelativeLayout>

    <EditText
        android:id="@+id/note_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textColor="#333"
        android:textCursorDrawable="@null"
        android:background="@null"/>

</LinearLayout>


具体效果如下:


新建记事本的Activity如下:AddNoteActivity.java

package com.ikok.notepad.Activity;

import android.app.Activity;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.ikok.notepad.DBUtil.NoteDB;
import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by Anonymous on 2016/3/24.
 */
public class AddNoteActivity extends Activity {

    /**
     * 布局控件
     */
    private TextView mComplete;
    private ImageButton mBackBtn;
    private EditText mContent;
    /**
     * 备忘录数据
     */
    private String noteTime;
    private String noteContent;
    /**
     * 数据库
     */
    private NoteDB mNoteDB;
    private Note note;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.write_note);

        initView();
        initEvent();
    }

    private void initView() {
        /**
         * 布局控件初始化
         */
        mComplete = (TextView) findViewById(R.id.complete_btn);
        mBackBtn = (ImageButton) findViewById(R.id.back_btn);
        mContent = (EditText) findViewById(R.id.note_content);
        /**
         * 获取数据库实例
         */
        mNoteDB = NoteDB.getInstance(this);
    }

    /**
     * 事件处理
     */
    private void initEvent() {
        /**
         * 返回上一级菜单,如果有内容,提示是否保存
         * 是、保存,销毁活动;否,直接销毁活动
         */
        mBackBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                saveDataOrNot();
            }
        });

        /**
         * 完成按钮,保存备忘录到数据库
         */
        mComplete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!mContent.getText().toString().equals("")){
                    new AddAsyncTask().execute();
                    finish();
                } else {
                    finish();
                }
            }
        });
    }
    /**
     * 根据是否有内容,提示保存
     */
    private void saveDataOrNot() {
        if (!mContent.getText().toString().trim().equals("")) {
            new AlertDialog.Builder(AddNoteActivity.this)
                    .setTitle("提示")
                    .setMessage("需要保存您编辑的内容吗?")
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            new AddAsyncTask().execute();
                            finish();
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    })
                    .show();
        } else {
            finish();
        }
    }

    /**
     * 添加数据到数据库
     */
    class AddAsyncTask extends AsyncTask<Void,Void,Void>{

        @Override
        protected Void doInBackground(Void... voids) {
            mNoteDB.saveNote(note);
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            /**
             * 记录数据
             */
            SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm");
            Date date = new Date(System.currentTimeMillis());
            noteTime = sdf.format(date);
            noteContent = mContent.getText().toString();
            note = new Note();
            note.setTime(noteTime);
            note.setContent(noteContent);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            Toast.makeText(AddNoteActivity.this, "保存成功!", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 按返回键,有内容时,提示保存
     */
    @Override
    public void onBackPressed() {
        saveDataOrNot();
    }
}

新建记事本,插入数据到数据库,如从数据库读取数据一样,都是耗时操作,所以我还是用了AsyncTask,在 onPreExecute()方法中,先获取到系统当前时间,进行格式化,存储下来,把输入的文本存储下来,然后再 doInBackground()去保存数据。这里我考虑了,用户输入了内容,但是没有保存,在顶部的返回键或者系统的返回键的处理事件中都加了判断。如果文本为空,空格也算空,则不保存,直接退出当前Activity,如果有内容,则弹出对话框提示用户是否保存,是则保存,否则不保存,退出当前活动。


接下来是查看或修改一条记事本了,布局我是直接复用新建记事本的布局。因为没有区别 - - 


接下来是查看或修改一条记事本的Activity了,之前,我想的是点击一条记事本,则进入这条记事本,把这条记事本直接显示在页面上,用户直接在内容最后进行编辑。所以这里需要一个子项点击事件。我在MainActivity里已经写了,先获取当前点击的这一项的对象,这里我费了好多时间,我不知道点击这一项的时候,怎么把该项的对象读取出来。最后自己查看源码,查API,看到参数中AdapterView是个泛型,我试着从它着手,把它强转成Note对象,然后试试获取id,没想到就成了。 - -  

所以,我获取了当前点击的item中的Note对象的id,把它放在Intent中,带着这个参数去开启活动。

这里,查看或修改一条记事本的Activity正式开始了,如下:UpdateOrReadActivity.java

package com.ikok.notepad.Activity;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.ikok.notepad.DBUtil.NoteDB;
import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;
import com.ikok.notepad.Util.DeleteAsyncTask;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by Anonymous on 2016/3/24.
 */
public class UpdateOrReadActivity extends Activity {

    /**
     * 布局控件
     */
    private TextView mComplete;
    private ImageButton mBackBtn;
    private EditText mContent;
    private LinearLayout mScreen;
    /**
     * 备忘录数据
     */
    private int noteId;
    private String noteTime;
    private String noteContent;
    private String originData;
    /**
    * 数据库
    */
    private NoteDB mNoteDB;
    private static Note note;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.write_note);
        /**
         * 获取传递过来的note对象
         */
        Intent intent = getIntent();
        // 传递Note对象,必须要Note实体实现Serializable
//        note = (Note) intent.getSerializableExtra("note_item");
        noteId = intent.getIntExtra("note_id",0);
        Log.d("Anonymous", "传递后的备忘录ID:" + noteId);

        initView();
        /**
         * 加载显示数据
         */
        new LoadAsyncTask().execute();
        initEvent();
    }

    private void initView() {
        /**
         * 布局控件初始化
         */
        mComplete = (TextView) findViewById(R.id.complete_btn);
        mBackBtn = (ImageButton) findViewById(R.id.back_btn);
        mContent = (EditText) findViewById(R.id.note_content);
        mScreen = (LinearLayout) findViewById(R.id.screen_view);
        /**
         * 获取数据库实例
         */
        mNoteDB = NoteDB.getInstance(this);
    }

    private void initEvent() {
        /**
         * 返回上一级菜单,直接销毁当前活动
         */
        mBackBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                updateDataOrNot();
            }
        });
        /**
         * 完成按钮,修改备忘录到数据库
         */
        mComplete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mContent.getText().toString().trim().equals("")){
//                    Log.d("Anonymous","进入判断为空函数");
                    new DeleteAsyncTask(mNoteDB).execute(noteId);
                    finish();
                } else if (mContent.getText().toString().equals(originData)) {
                    finish();
                } else {
//                    Log.d("Anonymous","进入判断不为空函数");
                    new UpdateAsyncTask().execute();
//                    Toast.makeText(UpdateOrReadActivity.this, "修改成功!", Toast.LENGTH_SHORT).show();
                    finish();
                }
            }
        });
        /**
         * 点击屏幕空白区域,EditText选中
         */


    }

    /**
     * 根据id从数据库读数据的异步任务
     */
    class LoadAsyncTask extends AsyncTask<Void,Void,Note>{

        @Override
        protected Note doInBackground(Void... voids) {
            note = mNoteDB.loadById(noteId);
            return note;
        }

        @Override
        protected void onPostExecute(Note note) {
            super.onPostExecute(note);
            /**
             * 根据传递进来的Note显示备忘录内容,并把光标移动到最后
             * 记录最初的文本内容
             */
            originData = note.getContent();
            mContent.setText(note.getContent());
            mContent.setSelection(mContent.getText().toString().length());
        }
    }
    /**
     * 更新数据库的异步任务
     */
    class UpdateAsyncTask extends AsyncTask<Void,Void,Void>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            /**
             * 记录数据
             */
            SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm");
            Date date = new Date(System.currentTimeMillis());
            noteTime = sdf.format(date);
            noteContent = mContent.getText().toString();
            note.setTime(noteTime);
            note.setContent(noteContent);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            mNoteDB.updateById(noteTime, noteContent, noteId);
            return null;
        }
    }
    /**
     * 根据是否有内容,提示保存
     */
    private void updateDataOrNot() {
        if (!mContent.getText().toString().equals(originData)) {
            new AlertDialog.Builder(UpdateOrReadActivity.this)
                    .setTitle("提示")
                    .setMessage("需要保存您编辑的内容吗?")
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            new UpdateAsyncTask().execute();
                            finish();
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    })
                    .show();
        } else {
            finish();
        }
    }
    /**
     * 返回键事件
     * 根据内容是否有变化,提示是否保存
     */
    @Override
    public void onBackPressed() {
        updateDataOrNot();
    }
}


操作数据库还是用了AsyncTask。这里,我考虑了,是否有改动,用一个变量,去存放原始的数据,在用户点击顶部返回或者系统返回键的时候去判断是否有改动,如果有,则提示用户是否需要保存更改。如果修改内容,没有字了,则自动删除该条记事本。因为删除记事本的操作,在主页还需要用到,所以我把它提出来,单独作为一个类,不再是内部类了。如下:

package com.ikok.notepad.Util;

import android.os.AsyncTask;

import com.ikok.notepad.DBUtil.NoteDB;

/**
 * Created by Anonymous on 2016/3/25.
 */
public class DeleteAsyncTask extends AsyncTask<Integer,Void,Void> {

    private NoteDB noteDB;

    public DeleteAsyncTask(NoteDB noteDB) {
        this.noteDB = noteDB;
    }

    @Override
    protected Void doInBackground(Integer... params) {
        noteDB.deleteById(params[0]);
        return null;
    }

}


接下来是CRUD的最后一项,删除数据了,在主页的时候,我设计的是单击进入该条记事本,去查看或修改这一条记事本,然后我考虑的是长按删除。长按,弹出对话框,提示是否删除,是则删除,否则不做任何事。所以在MainActivity中可以看到长按事件的监听器。但是因为Android的事件分发机制,长按事件必定会触发点击事件。所以需要在ListView中设置这样一个属性,才能点击事件和长按事件同时监听。

android:descendantFocusability="blocksDescendants"


主要功能都差不多完成了。接下来就是优化App了。我设计了过渡动画,引导页,以及是否第一次启动App。是则过渡动画过渡完到引导页,引导页完才到主页。否则过渡动画过渡完则直接进入主页。还设计了引导页的切换动画,使用了nineoldandroid,保证动画在低版本手机上可显示。


优化App部分可见我另外一篇博客,传送门: http://blog.csdn.net/someone_ikok/article/details/51027357



项目地址在:https://github.com/someonexiaole/Android

Notepad 即是。


欢迎大家 pr , star , fork , follow  我的 Github。


©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页