学了极客学院一个开发记事本的课程,利用自己对MVC编程模式的简单理解重写了一遍该app。

  github地址:https://github.com/morningsky/MyNote

MVC即,模型(model)-视图(view)-控制器(controller),有效的实现了数据-业务逻辑-视图显示的代码分离,使得加入新功能时不需要重新编写业务逻辑,大大提高了代码的可维护性。

  

  

   在这个案列中,一开始只是开发了添加文字内容的记事功能,添加图片功能时在activity文件中写入imageview的逻辑 在数据库中加入图片路径数据 在视图中加一个imageview的。后期若再添加视频功能可参照之前添加图片的操作快速实现app的升级。整个代码编写过程脉络清晰,加上Android Studio的帅气主题,开发过程感觉极好。

  

下面是整个app的开发流程:

/*步骤:
1.model构建
  1.1创建数据库 NoteDB类
  1.2创建自定义的adapter MyAdapter类
    1.2.1构造函数
    1.2.2复写4个子类方法 注意getView方法

2.创建视图
  2.1布局主界面 两个按钮 一个listview activity_main.xml
  2.2 listview每一条数据的视图格式 图片imageview 内容textview 时间textview cell.xml
  2.3添加内容界面 imageview editext 两个Button addcontent.xml
  2.4创建详情页视图 与addcontent视图相似 将Editext转换为Textview Button的内容由返回变成删除 incontent.xml

3.逻辑实现
  MainActivity:
    3.1初始化主界面布局 定义initView方法 给按钮设置监听
    3.7在MainActivity实例化一个SQLiteDatabase 获取读取权限 用于加载listview的内容
    3.8添加查询数据方法selectDB 并在该方法中加载MyAdapter
  

  AddContent:
    3.2创建添加内容界面的activity 并在AndroidManifest文件中注册该activity 两个activity添加固定竖屏参数
    3.3初始化AddContent界面布局 定义initView方法 给按钮设置监听 实例化SQLiteDatabase 获取写入数据权限
    3.4添加addDB方法获取内容 时间并写入数据库
    3.5添加getTime方法获取系统当前时间
    3.6为按钮添加事件
    3.9增加根据添加文字还是图文加载不同界面的initView逻辑
    4.0添加Intent调用系统相机 实例化一个File存放照片路径
    4.1复写onActivityResult来查看照片效果
    4.2add函数添加图片路径

  MyAdapter:
    4.3添加查看缩略图函数getImageThumbnail listview中显示
    4.5添加用来查询的String path 储存地址

  InContent:
    4.6添加详情页Activity 并注册
    4.7给listview添加监听事件 跳转到详情页 并传入部分数据
    4.8根据图文还是文字加载不同视图 显示文字 图片信息
    4.9实例化一个SQLiteDatabase 获取写入数据权限 用来删除数据
    5.0添加删除数据方法delDB 给按钮加上方法
*/

  

  model层:

    NoteDB.java 创建了一个数据库 用来存放记事内容 记事时间 图片路径

    

 package com.bluesky.mynote;

 import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; /**
* Created by 清晨 on 2015/5/6.
*/
public class NoteDB extends SQLiteOpenHelper { public static final String TABLE_NAME="notes";//表名
public static final String CONTENT="content";//内容
public static final String ID="id"; //标识每一条数据
public static final String TIME="time"; //存放添加数据时的时间
public static final String PATH="path"; //路径,用来存放照片路径 //构造函数参数保留一个Content即可
public NoteDB(Context context) {
super(context, "notes", null, 1);
} //注意属性内的空格 " TEXT NOT NULL,"第一个引号后的空格不能省略 否则名称会变为contentTEXT
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " ("
+ ID+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ CONTENT+" TEXT NOT NULL,"
+ PATH +" TEXT NOT NULL,"
+ TIME +" TEXT NOT NULL)");
} //不需要更新
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

  MyAdapter.java 用来设定主界面listview的内容格式

 package com.bluesky.mynote;

 import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; /**
* Created by 清晨 on 2015/5/7.
*/
public class MyAdapter extends BaseAdapter {
private Context mContext;
private Cursor mCursor;
private LinearLayout layout; public MyAdapter(Context context,Cursor cursor){
mContext=context;
mCursor=cursor;
}
@Override
public int getCount() {
return mCursor.getCount();
} @Override
public Object getItem(int position) {
return mCursor.getPosition();
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=LayoutInflater.from(mContext);//加载视图权限
layout= (LinearLayout) inflater.inflate(R.layout.cell,null);//加载视图
//初始化控件
TextView content_tv= (TextView) layout.findViewById(R.id.list_content);
TextView time_tv= (TextView) layout.findViewById(R.id.list_time);
ImageView img_iv= (ImageView) layout.findViewById(R.id.list_img);
//查询mCursor 用String获取查询内容
mCursor.moveToPosition(position);
String content=mCursor.getString(mCursor.getColumnIndex("content"));
String time=mCursor.getString(mCursor.getColumnIndex("time"));
String url=mCursor.getString(mCursor.getColumnIndex("path"));
content_tv.setText(content);
time_tv.setText(time);
img_iv.setImageBitmap(getImageThumbnail(url,200,200));
return layout;
} //获取缩略图
public Bitmap getImageThumbnail(String uri,int width,int height){
Bitmap bitmap=null;
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
bitmap=BitmapFactory.decodeFile(uri,options);
options.inJustDecodeBounds=false;
int beWidth=options.outWidth/width;
int beHeight=options.outHeight/height;
int be=1;
//防止图片超出过大或过小不予缩小
if(beWidth<beHeight){
be=beWidth;
}else {
be=beHeight;
}
if(be<=0){
be=1;
}
options.inSampleSize=be;
bitmap=BitmapFactory.decodeFile(uri,options);
bitmap=ThumbnailUtils.extractThumbnail(bitmap,width,height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
return bitmap;
}
}

  视图层(View):

                        

分别是主界面 activity_main.xml    添加内容addcontent.xml  内容详情页incontent.xml

内容详情页与添加内容界面 基本相似 所以可实现代码的简单修改 将编辑框改为文本框 再修改相应ID即可

接下来是核心部分

  控制器(Controler):

    主activity:

 package com.bluesky.mynote;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView; public class MainActivity extends ActionBarActivity implements View.OnClickListener {
private Button text_btn, img_btn;
private ListView lv;
private Intent i;
private MyAdapter adapter;
private NoteDB noteDB;
private SQLiteDatabase dbReader;
private Cursor cursor; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//给按钮加入监听事件
text_btn.setOnClickListener(this);
img_btn.setOnClickListener(this);
noteDB = new NoteDB(this);
//获取读取权限 用于加载listview的内容
dbReader = noteDB.getReadableDatabase();
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
cursor.moveToPosition(position);//游标挪到了position的位置上
Intent i=new Intent(MainActivity.this,InContent.class);
i.putExtra(NoteDB.ID,cursor.getInt(cursor.getColumnIndex(NoteDB.ID)));//以便根据ID删除数据
i.putExtra(NoteDB.CONTENT,cursor.getString(cursor.getColumnIndex(NoteDB.CONTENT)));
i.putExtra(NoteDB.TIME,cursor.getString(cursor.getColumnIndex(NoteDB.TIME)));
i.putExtra(NoteDB.PATH,cursor.getString(cursor.getColumnIndex(NoteDB.PATH)));
startActivity(i);
}
}); } //初始化控件
public void initView() {
lv = (ListView) findViewById(R.id.list);
text_btn = (Button) findViewById(R.id.text);
img_btn = (Button) findViewById(R.id.image);
} //查询数据
public void selectDB() {
cursor = dbReader.query(NoteDB.TABLE_NAME,null,null,null,null,null,null,null);
adapter = new MyAdapter(this,cursor);
lv.setAdapter(adapter);
} @Override
public void onClick(View v) {
i = new Intent(this, AddContent.class);
switch (v.getId()) {
case R.id.text:
i.putExtra("flag", "1");
startActivity(i);
break;
case R.id.image:
i.putExtra("flag", "2");
startActivity(i);
break;
}
} @Override
protected void onResume() {
super.onResume();
selectDB();
}
}

添加内容 activity

  

 package com.bluesky.mynote;

 import android.app.Activity;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.PersistableBundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.VideoView; import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date; /**
* Created by 清晨 on 2015/5/6.
*/
public class AddContent extends Activity implements View.OnClickListener {
private NoteDB noteDB;
private SQLiteDatabase dbWriter;
private String flag; //接受从mainactivity传来的标识 用于判定加载不同的添加内容界面(图文或者纯文字)
private EditText editText;
private Button save_btn,cancel_btn;
private ImageView c_img;
private File imgfile;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.addcontent);
flag=getIntent().getStringExtra("flag");
initView();
save_btn.setOnClickListener(this);
cancel_btn.setOnClickListener(this);
noteDB=new NoteDB(this);
dbWriter=noteDB.getWritableDatabase();//获取写入数据库权限
} //初始化控件
public void initView(){
editText= (EditText) findViewById(R.id.ettext);
save_btn= (Button) findViewById(R.id.save);
cancel_btn= (Button) findViewById(R.id.cancel);
c_img= (ImageView) findViewById(R.id.c_img);
if(flag.equals("1")){
c_img.setVisibility(View.GONE);//隐藏imageview
}
if(flag.equals("2")){
c_img.setVisibility(View.VISIBLE);//显示imageview
//启动系统相机拍照
Intent getImg=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//图片是放在存储卡中 路径存在数据库中 以时间命名图片 避免重名
imgfile=new File(Environment.getExternalStorageDirectory()
.getAbsolutePath()+"/"+getTime()+".jpg");
getImg.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imgfile));
startActivityForResult(getImg,1);//便于立即查看效果 }
} //获取内容并写入数据库
public void addDB(){
ContentValues cv=new ContentValues();
cv.put(NoteDB.CONTENT,editText.getText().toString());
cv.put(NoteDB.TIME,getTime());
cv.put(NoteDB.PATH,imgfile + "");
dbWriter.insert(NoteDB.TABLE_NAME,null,cv);
} //获取系统当前时间
public String getTime(){
SimpleDateFormat format=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date curDate=new Date();
String str=format.format(curDate);
return str;
} @Override
public void onClick(View v) {
switch (v.getId()){
case R.id.save:
addDB();
finish();
break;
case R.id.cancel:
finish();
break; } } //预览显示拍摄内容
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==1){
Bitmap bitmap= BitmapFactory.decodeFile(imgfile.getAbsolutePath());
c_img.setImageBitmap(bitmap);
}
}
}

内容详情页Activity

 package com.bluesky.mynote;

 import android.app.Activity;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView; /**
* Created by 清晨 on 2015/5/8.
*/
public class InContent extends Activity implements View.OnClickListener {
private Button del_btn;
private Button back_btn;
private ImageView in_img;
private TextView in_tv;
private NoteDB noteDB;
private SQLiteDatabase dbWriter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.incontent);
initView();
noteDB= new NoteDB(this);
dbWriter=noteDB.getWritableDatabase();
del_btn.setOnClickListener(this);
back_btn.setOnClickListener(this);
//根据记事方式加载不同视图
if(getIntent().getStringExtra(NoteDB.PATH).equals("null")){
in_img.setVisibility(View.GONE);
}else {
in_img.setVisibility(View.VISIBLE);
}
//显示文字
in_tv.setText(getIntent().getStringExtra(NoteDB.CONTENT));
//显示图片
Bitmap bitmap= BitmapFactory.decodeFile(getIntent().getStringExtra(NoteDB.PATH));
in_img.setImageBitmap(bitmap);
} public void initView(){
del_btn= (Button) findViewById(R.id.delete);
back_btn= (Button) findViewById(R.id.back);
in_img= (ImageView) findViewById(R.id.in_img);
in_tv= (TextView) findViewById(R.id.in_tv);
} @Override
public void onClick(View v) {
switch (v.getId()){
case R.id.delete:
delDB();
finish();
break;
case R.id.back:
finish();
break;
}
}
//删除数据
public void delDB(){
dbWriter.delete(NoteDB.TABLE_NAME,"id="+getIntent()
.getIntExtra(NoteDB.ID,0),null);
}
}

  新人一枚,初学安卓,也初次尝试着写博客,暂且把这一路的code time记下来吧.

利用MVC编程模式-开发一个简易记事本app的更多相关文章

  1. MVC编程模式

    MVC编程模式 MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式: Model(模型)表示应用程序核心(比如数据库记录列表) ...

  2. 利用JSP编程技术实现一个简单的购物车程序

    实验二   JSP编程 一.实验目的1. 掌握JSP指令的使用方法:2. 掌握JSP动作的使用方法:3. 掌握JSP内置对象的使用方法:4. 掌握JavaBean的编程技术及使用方法:5. 掌握JSP ...

  3. 使用Phalcon框架开发一个简易的博客系统

    使用Phalcon PHP框架开发一个简易的博客系统(类似于CMS) 最近在做Phalcon(Phalcon在英文中指的是鸟类中飞得最快的那一个物种,由于是高性能框架,借用了这个词)相关的项目,由于刚 ...

  4. android开发学习---开发一个简易的短信发送器

    一.需求: 开发一个简易的短信发送器,输入:对方手机号码,短信内容,点击发送按钮,短信发送成功,对方手机成功收到短信. 其中要求短信内容过长时可以自动拆分,长度英文是160个英文,中文是70个,中英混 ...

  5. jQuery 开发一个简易插件

    jQuery 开发一个简易插件 //主要内容 $.changeCss = function(options){ var defaults = { color:'blue', ele:'text', f ...

  6. 移动跨平台开发框架Ionic开发一个新闻阅读APP

    移动跨平台开发框架Ionic开发一个新闻阅读APP 前言 这是一个系列文章,从环境搭建开始讲解,包括网络数据请求,将持续更新到项目完结.实战开发中遇到的各种问题的解决方案,也都将毫无保留的分享给大家. ...

  7. ASP.NET没有魔法——ASP.NET MVC使用Area开发一个管理模块

    之前的My Blog提供了列表的展示和文章显示功能,但是所有数据仍然只能通过数据库录入,为了完成最初的角色“作者”的用例,本章将介绍如何使用“Area”实现My Blog的管理功能. 根据功能分离代码 ...

  8. 利用阿里云如何开发一款直播app?

    在开发的过程中应该注意些什么?下面让小编告诉你: 随着互联网的发展,越来越多的人已经加入互联网的行列.而且很多的人也开始直播,和众多的网友分享自己身边事情.互联网还在加速发展,从PC互联网,到移动互联 ...

  9. 如何用django开发一个简易个人Blog

    功能概要:(目前已实现功能) 公共展示部分: 1.网站首页展示已发布的博客记录,包括名称.摘要信息.发布日期.阅读量及评论数. 2.首页文章列表可按照分类筛选. 3.点击标题或阅读全文链接,进入博客阅 ...

随机推荐

  1. XBox360-双光盘游戏自制GOD

    一直在找极限竞速4(Forza4),虽然这个版本比较老,但因为带体感.终于下到了,可惜是2个ISO.试着自己做GOD.用到两个软件:Iso2God和Xbox Backup Creator(俗称XBC) ...

  2. Kafka单机版环境搭建

    使用版本:kafka_2.10-0.8.1.1 安装: -0.8.1.1.tgz -C ~/app/ 添加环境变量:.bash_profile export KAFKA_HOME=/home/spar ...

  3. nginx 编译模块说明

    --prefix= <path> - Nginx安装路径.如果没有指定,默认为 /usr/local/nginx. --sbin-path= <path> - Nginx可执行 ...

  4. CSS用border绘制三角形

    使用border绘制三角形的思路,就是border尺寸设置一个较大的值,元素自身的宽高设置为0,全部由边线占据,这样每边就会显示为四分之一块的三角形.这样不借助图片,可以直接绘制出三角形了. 一个栗子 ...

  5. 2013款Mac Pro“神秘”主机详解

    2013款Mac Pro"神秘"主机详解 自2013年12月下旬新款Mac Pro在美国发布以来,经过一个月的等待终于在国内已到货,笔者亲自测试了这个号称"神秘" ...

  6. ionic icons and splash

    ionic 用cordova  可以直接设置自己的icons ,不用修改默认的图片了 1.在自己的根目录下新建一个文件夹 如icons 2.然后在icons文件夹下再建一个iOS 文件夹存放所需要的图 ...

  7. gitlb gerrit jenkins CI整合调试

  8. HTML中解决双击会选中文本的问题

    HTML中解决双击会选中文本的问题 <div unselectable="on" style="-moz-user-select:none;" onsel ...

  9. jsp页面el表达式不起作用

    web.xml中2.4版本的默认导入的standerd.jar,和jstl.jar是使用el表达式的包是启动的而2.5版本的web.xml中默认是关闭的所以在2.5的所有jsp中需要启动一下用< ...

  10. JavaScript编程规范

    最近看NodeJS中,有一部分写JS约定俗成的编程规范(附录B,详情参考附件),感觉在实际工作中能用到, 大致意思分享给大家,详情参考附件: 1.缩进:建议两空格 作为Node.js代码的缩进标记: ...