Kotlin开发安卓APP笔记实战-写个简易记事本(逻辑)

元旦前事情不少,拖到现在才写,有点尴尬。写了代码才知道前一篇写的笔记有些不正确,在这一篇笔记慢慢指出来,也不更新前一篇笔记了。学习就是这样一个发现错误并改正错误的过程。
先看最终效果图
这里写图片描述
这里写图片描述
由于工作关系,RecyclerView没有画分割线,如果需要的话可以参考郭神的Android RecyclerView 使用完全解析 体验艺术般的控件
用到的返回和保存按钮图标在图标查询网下载

创建一个DbHelper类连接数据库并初始化数据库结构

package cn.bestmk.note

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

/**
 * Created by 醉猫 on 2017/12/26.
 */

class DBHelper(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
    override fun onCreate(sqLiteDatabase: SQLiteDatabase) {
        // create table if not exists note(ID INT PRIMARY KEY NOT NULL,createtime TIMESTAMP NOT NULL,chagetime TIMESTAMP,title CHAR(255) NOT NULL,content TEXT NOT NULL);
        val sql = "create table if not exists $TABLE_NAME(ID INTEGER PRIMARY KEY AUTOINCREMENT,createtime TIMESTAMP NOT NULL,chagetime TIMESTAMP,title CHAR(255) NOT NULL,content TEXT NOT NULL);"
        sqLiteDatabase.execSQL(sql)
    }
    override fun onUpgrade(sqLiteDatabase: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        val sql = "DROP TABLE IF EXISTS " + TABLE_NAME
        sqLiteDatabase.execSQL(sql)
        onCreate(sqLiteDatabase)
    }
    //声明静态变量
    companion object {
        private val DB_VERSION = 1
        private val DB_NAME = "note.db"
        private val TABLE_NAME = "note"
    }
}

从代码中看出这里的sql语句和上一篇笔记(ID INT PRIMARY KEY NOT NULL)并不一致,这里是ID INTEGER PRIMARY KEY AUTOINCREMENT,前面的语句是设置ID为主键并且不能为空,后面是ID为主键,并且自动增长,越是细节的地方越容易出错。

创建一个NoteBean保存笔记数据,可以理解为kotlin的Javabean

package cn.bestmk.note

/**
 * Created by 醉猫 on 2017/12/29.
 */

class NoteBean {
    var id: Int = 0
    var createTime: Long = 0
    var chageTime: Long = 0
    var title: String? = null
    var content: String? = null
}

创建一个NoteManager管理笔记(增删改查)

package cn.bestmk.note

import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.util.Log

/**
 * Created by 醉猫 on 2017/12/27.
 */
class NoteManager(contxt: Context){
    val db:SQLiteDatabase
    init {
        db= DBHelper(contxt).writableDatabase
    }

    /**
     * 添加一条笔记
     */
    fun addNote(title:String,content:String){
        var nowtime=System.currentTimeMillis()
        var sql="insert into note (createtime, chagetime, title,content) values ($nowtime,$nowtime,'$title','$content')"
        db.execSQL(sql)
    }

    /**
     * 删除一条笔记
     */
    fun deleteNote(id:Int){
        var sql="delete from note where ID=$id"
        db.execSQL(sql)
    }

    /**
     * 修改一条笔记
     */
    fun chageNote(id:Int,title: String,content: String){
        var nowtime=System.currentTimeMillis()
        var sql="update note set title='$title',content='$content',chagetime='$nowtime' where ID=$id"
        db.execSQL(sql)
    }

    /**
     * 查询笔记
     */
    fun queryNote(id: Int):NoteBean{
        val bean=NoteBean()
        var sql="select * from note where ID=$id"
        var cursor=db.rawQuery(sql,null) //执行查询语句
        if (cursor.moveToNext()){
            bean.id=cursor.getInt(0) //获取id
            bean.createTime=cursor.getLong(1) //获取创建时间
            bean.chageTime=cursor.getLong(2)//获取上次修改时间
            bean.title=cursor.getString(3)//获取标题
            bean.content=cursor.getString(4)//获取内容
        }
        return bean
    }

    /**
     * 查询所有笔记
     */
    fun queryNotes():ArrayList<NoteBean>{
        val list: ArrayList<NoteBean> = arrayListOf()//创建集合
        var sql="select * from note" //构建查询语句
        var cursor=db.rawQuery(sql,null) //执行查询语句
        while (cursor.moveToNext()){ //设置循环语句
            val bean=NoteBean()
            bean.id=cursor.getInt(0) //获取id
            bean.createTime=cursor.getLong(1) //获取创建时间
            bean.chageTime=cursor.getLong(2)//获取上次修改时间
            bean.title=cursor.getString(3)//获取标题
            bean.content=cursor.getString(4)//获取内容
            list.add(bean) //添加一条笔记到集合
        }
        return list
    }
}

注释写得比较详细,就不再多说

为RecyclerView创建一个适配器NoteAdapter.kt

package cn.bestmk.note

import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.support.v7.widget.RecyclerView
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import cn.bestmk.note.NoteAdapter.ViewHolder

import org.w3c.dom.Text
import java.text.SimpleDateFormat
import java.util.*

/**
 * Created by 醉猫 on 2017/12/29.
 */

class NoteAdapter(var context:Context,var mData: ArrayList<NoteBean>?) : RecyclerView.Adapter<NoteAdapter.ViewHolder>() {

    fun updateData(data: ArrayList<NoteBean>) {
        this.mData = data
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // 实例化展示的view
        val v = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
        // 实例化viewholder
        return ViewHolder(v)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        var sdFormat= SimpleDateFormat("yyyy-MM-dd HH:mm:ss")//时间转换器
        // 绑定数据
        holder.tv_title.setText(mData!![position].title)
        holder.tv_createtime.setText("创建时间:"+sdFormat.format(Date(mData!![position].createTime)))//显示转换后的创建时间
        holder.tv_chagetime.setText("修改时间:"+sdFormat.format(Date(mData!![position].chageTime)))//显示转换后的创建时间
        holder.itemView.setOnClickListener { view ->
            val intent=Intent(context,EditActivity::class.java)
            intent.putExtra("ID", mData!![position].id) //向EditActivity传递ID
            context.startActivity(intent)
        }
        holder.itemView.setOnLongClickListener(object :View.OnLongClickListener{
            override fun onLongClick(p0: View?): Boolean {
                AlertDialog.Builder(context).setTitle("骚气的提示") .setMessage("是否要删除本条笔记").setPositiveButton("是",object :DialogInterface.OnClickListener{
                    override fun onClick(p0: DialogInterface?, p1: Int) {
                        NoteManager(context).deleteNote(position)//删除笔记
                        mData!!.removeAt(position)//更新集合数据
                        updateData(mData!!)//刷新页面数据
                        Toast.makeText(context,"删除成功",Toast.LENGTH_LONG).show()
                    }
                }).setNegativeButton("取消",null).show()
                return false
            }
        })
    }

    override fun getItemCount(): Int {
        return if (mData == null) 0 else mData!!.size
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        internal var tv_title: TextView
        internal var tv_createtime: TextView
        internal var tv_chagetime: TextView

        init {
            tv_title = itemView.findViewById(R.id.tv_title)
            tv_createtime = itemView.findViewById(R.id.tv_createtime)
            tv_chagetime = itemView.findViewById(R.id.tv_chagetime)
        }
    }
}

MainActivity.kt

package cn.bestmk.note

import android.content.Intent
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.widget.AdapterView

import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    lateinit var nm: NoteManager //声明笔记管理器
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)

        nm = NoteManager(this)//初始化笔记管理器
        rv.layoutManager = LinearLayoutManager(this) as RecyclerView.LayoutManager?//设置布局管理器

        //右下悬浮按钮事件
        fab.setOnClickListener { view ->
            var intent = Intent(this@MainActivity, EditActivity::class.java)
            startActivity(intent)
        }
    }
    //在onStart中设置适配器,每次显示MainActivity都会更新一次数据
    override fun onStart() {
        rv.adapter = NoteAdapter(this, nm.queryNotes())//设置适配器
        super.onStart()
    }
}

EditActivity.kt

package cn.bestmk.note

import android.app.AlertDialog
import android.content.DialogInterface
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent
import android.view.Menu
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_edit.*

class EditActivity : AppCompatActivity() {
    lateinit var nm: NoteManager
    var ID: Int = -1 //ID
    var ischage = false
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_edit)

        setSupportActionBar(toolbar)//为当前的Activity设置标题栏
        nm = NoteManager(this)//获取笔记管理器实例
        title = ""

        ID = intent.getIntExtra("ID", -1)//获取ID,设置默认值为-1,也就是没有传递参数会传-1
        if (ID >= 0) {//如果id大于或等于0,就说明用户是点击item进入EditActivity,是修改或查看笔记,否则是新增笔记
            var bean = nm.queryNote(ID)//查询这条ID的内容
            ettitle.setText(bean.title)//显示标题
            etcontent.setText(bean.content)//显示内容
        }
        //为save按钮绑定事件
        toolbar.setOnMenuItemClickListener {
            if (ettitle.text.length < 0) {//判断标题是否为空
                Toast.makeText(this@EditActivity, "标题不可为空", Toast.LENGTH_LONG).show()
                return@setOnMenuItemClickListener false
            }
            if (etcontent.text.length < 0) {//判断内容是否为空
                Toast.makeText(this@EditActivity, "内容不可为空", Toast.LENGTH_LONG).show()
                return@setOnMenuItemClickListener false
            }
            save()
            finish()//关闭当前页面
            false
        }
        back.setOnClickListener {
            back()
        }
        //监听标题改变事件
        ettitle.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                ischage = true //将笔记改变状态设置成true
            }

        })
        //监听内容改变事件
        etcontent.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) {
            }

            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                ischage = true //将笔记改变状态设置成true
            }

        })
    }
    //保存笔记函数
    fun save(){
        if (ID >= 0) {//修改
            nm.chageNote(ID, ettitle.text.toString(), etcontent.text.toString())//修改这条笔记
            Toast.makeText(this@EditActivity, "修改成功", Toast.LENGTH_LONG)
        } else {//新增
            nm.addNote(ettitle.text.toString(), etcontent.text.toString())//数据库新增一条笔记
            Toast.makeText(this@EditActivity, "保存成功", Toast.LENGTH_LONG).show()
        }
    }
    //返回函数
    fun back(){
        //如果笔记被修改就弹出窗口提示用户笔记被修改,询问用户是否要保存/修改笔记
        if (ischage){
            AlertDialog.Builder(this).setTitle("骚气的提示").setMessage("您的笔记尚未保存,是否保存?").setPositiveButton("保存",object :DialogInterface.OnClickListener{
                override fun onClick(p0: DialogInterface?, p1: Int) {
                    save()
                    finish()
                }
            }).setNegativeButton("不保存",object :DialogInterface.OnClickListener{
                override fun onClick(p0: DialogInterface?, p1: Int) {
                    finish()
                }
            }).setNeutralButton("取消",null).show()
        }else{
            finish()
        }
    }
    // 为toolbar创建Menu
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }
    //拦截返回键
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode==KeyEvent.KEYCODE_BACK){
            back()
            return true
        }
        return super.onKeyDown(keyCode, event)
    }
}

xml相对比前一篇笔记有一些小的调整,就不贴出来了
源码下载地址我会放在猫客技术论坛同名贴子下面,需要的可以下载下来看看

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
为了满足广大Android开发爱好者与从业者的学习需求,我们精心整理并上传了一份全面而实用的Android项目资源包。这份资源包内容丰富,涵盖了从基础知识到实战应用的全方位内容,旨在为开发者们提供一个便捷、高效的学习平台。 一、文件手册 资源包中的文件手册部分,详细记录了Android开发的核心知识点和常用技术。无论是初学者还是有一定经验的开发者,都能从中找到所需的学习资料。手册采用了简洁明了的排版方式,使得查阅更加方便快捷。同时,手册内容深入浅出,既适合新手入门,也能为老手提供有价值的参考。 二、项目实战与练习 为了让学习者能够将理论知识与实践相结合,我们特别准备了项目实战与练习部分。这部分内容包含了多个精心设计的Android项目案例,从需求分析、设计思路到实现过程,都有详细的讲解和代码示例。学习者可以通过实际操作,深入了解Android开发的整个流程,提升自己的实战能力。 此外,我们还提供了一系列练习题,旨在巩固所学知识,检验学习成果。这些练习题既有基础题,也有难度较高的挑战题,适合不同层次的学习者进行练习。 三、Android开发工具集 在Android开发过程中,选择合适的工具能够大大提高开发效率。因此,我们整理了常用的Android开发工具集,包括开发工具、测试工具、性能优化工具等。这些工具都是经过我们精心筛选和测试的,能够帮助开发者们更加高效地进行Android开发工作。 总的来说,这份Android项目资源包是一份不可多得的学习资料,无论你是初学者还是有一定经验的开发者,都能从中受益匪浅。我们希望通过这份资源包,为广大Android开发爱好者与从业者提供一个更加便捷、高效的学习平台,共同推动Android开发领域的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值