利用MVC编程模式-开发一个简易记事本app

  学了极客学院一个开发记事本的课程,利用自己对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 创建了一个数据库 用来存放记事内容 记事时间 图片路径

    

 1 package com.bluesky.mynote;
 2
 3 import android.content.Context;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.database.sqlite.SQLiteOpenHelper;
 6
 7 /**
 8  * Created by 清晨 on 2015/5/6.
 9  */
10 public class NoteDB extends SQLiteOpenHelper {
11
12     public static final String TABLE_NAME="notes";//表名
13     public static final String CONTENT="content";//内容
14     public static final String ID="id";         //标识每一条数据
15     public static final String TIME="time";    //存放添加数据时的时间
16     public static final String PATH="path";   //路径,用来存放照片路径
17
18     //构造函数参数保留一个Content即可
19     public NoteDB(Context context) {
20         super(context, "notes", null, 1);
21     }
22
23     //注意属性内的空格 " TEXT NOT NULL,"第一个引号后的空格不能省略 否则名称会变为contentTEXT
24     @Override
25     public void onCreate(SQLiteDatabase db) {
26         db.execSQL("CREATE TABLE " + TABLE_NAME + " ("
27                 + ID+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
28                 + CONTENT+" TEXT NOT NULL,"
29                 + PATH +" TEXT NOT NULL,"
30                 + TIME +" TEXT NOT NULL)");
31     }
32
33     //不需要更新
34     @Override
35     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
36
37     }
38 }

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

 1 package com.bluesky.mynote;
 2
 3 import android.content.Context;
 4 import android.database.Cursor;
 5 import android.graphics.Bitmap;
 6 import android.graphics.BitmapFactory;
 7 import android.media.ThumbnailUtils;
 8 import android.view.LayoutInflater;
 9 import android.view.View;
10 import android.view.ViewGroup;
11 import android.widget.BaseAdapter;
12 import android.widget.ImageView;
13 import android.widget.LinearLayout;
14 import android.widget.TextView;
15
16 /**
17  * Created by 清晨 on 2015/5/7.
18  */
19 public class MyAdapter extends BaseAdapter {
20     private Context mContext;
21     private Cursor mCursor;
22     private LinearLayout layout;
23
24     public MyAdapter(Context context,Cursor cursor){
25         mContext=context;
26         mCursor=cursor;
27     }
28     @Override
29     public int getCount() {
30         return mCursor.getCount();
31     }
32
33     @Override
34     public Object getItem(int position) {
35         return mCursor.getPosition();
36     }
37
38     @Override
39     public long getItemId(int position) {
40         return position;
41     }
42
43     @Override
44     public View getView(int position, View convertView, ViewGroup parent) {
45         LayoutInflater inflater=LayoutInflater.from(mContext);//加载视图权限
46         layout= (LinearLayout) inflater.inflate(R.layout.cell,null);//加载视图
47         //初始化控件
48         TextView content_tv= (TextView) layout.findViewById(R.id.list_content);
49         TextView time_tv= (TextView) layout.findViewById(R.id.list_time);
50         ImageView img_iv= (ImageView) layout.findViewById(R.id.list_img);
51         //查询mCursor 用String获取查询内容
52         mCursor.moveToPosition(position);
53         String content=mCursor.getString(mCursor.getColumnIndex("content"));
54         String time=mCursor.getString(mCursor.getColumnIndex("time"));
55         String url=mCursor.getString(mCursor.getColumnIndex("path"));
56         content_tv.setText(content);
57         time_tv.setText(time);
58         img_iv.setImageBitmap(getImageThumbnail(url,200,200));
59         return layout;
60     }
61
62     //获取缩略图
63     public Bitmap getImageThumbnail(String uri,int width,int height){
64         Bitmap bitmap=null;
65         BitmapFactory.Options options=new BitmapFactory.Options();
66         options.inJustDecodeBounds=true;
67         bitmap=BitmapFactory.decodeFile(uri,options);
68         options.inJustDecodeBounds=false;
69         int beWidth=options.outWidth/width;
70         int beHeight=options.outHeight/height;
71         int be=1;
72         //防止图片超出过大或过小不予缩小
73         if(beWidth<beHeight){
74             be=beWidth;
75         }else {
76             be=beHeight;
77         }
78         if(be<=0){
79             be=1;
80         }
81         options.inSampleSize=be;
82         bitmap=BitmapFactory.decodeFile(uri,options);
83         bitmap=ThumbnailUtils.extractThumbnail(bitmap,width,height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
84         return bitmap;
85     }
86 }

  视图层(View):

                        

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

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

接下来是核心部分

  控制器(Controler):

    主activity:

 1 package com.bluesky.mynote;
 2 import android.content.Intent;
 3 import android.database.Cursor;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.support.v7.app.ActionBarActivity;
 6 import android.os.Bundle;
 7 import android.view.View;
 8 import android.widget.AdapterView;
 9 import android.widget.Button;
10 import android.widget.ListView;
11
12
13 public class MainActivity extends ActionBarActivity implements View.OnClickListener {
14     private Button text_btn, img_btn;
15     private ListView lv;
16     private Intent i;
17     private MyAdapter adapter;
18     private NoteDB noteDB;
19     private SQLiteDatabase dbReader;
20     private Cursor cursor;
21
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.activity_main);
26         initView();
27         //给按钮加入监听事件
28         text_btn.setOnClickListener(this);
29         img_btn.setOnClickListener(this);
30         noteDB = new NoteDB(this);
31         //获取读取权限 用于加载listview的内容
32         dbReader = noteDB.getReadableDatabase();
33         lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
34             @Override
35             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
36                 cursor.moveToPosition(position);//游标挪到了position的位置上
37                 Intent i=new Intent(MainActivity.this,InContent.class);
38                 i.putExtra(NoteDB.ID,cursor.getInt(cursor.getColumnIndex(NoteDB.ID)));//以便根据ID删除数据
39                 i.putExtra(NoteDB.CONTENT,cursor.getString(cursor.getColumnIndex(NoteDB.CONTENT)));
40                 i.putExtra(NoteDB.TIME,cursor.getString(cursor.getColumnIndex(NoteDB.TIME)));
41                 i.putExtra(NoteDB.PATH,cursor.getString(cursor.getColumnIndex(NoteDB.PATH)));
42                 startActivity(i);
43             }
44         });
45
46     }
47
48     //初始化控件
49     public void initView() {
50         lv = (ListView) findViewById(R.id.list);
51         text_btn = (Button) findViewById(R.id.text);
52         img_btn = (Button) findViewById(R.id.image);
53     }
54
55     //查询数据
56     public void selectDB() {
57         cursor = dbReader.query(NoteDB.TABLE_NAME,null,null,null,null,null,null,null);
58         adapter = new MyAdapter(this,cursor);
59         lv.setAdapter(adapter);
60     }
61
62     @Override
63     public void onClick(View v) {
64         i = new Intent(this, AddContent.class);
65         switch (v.getId()) {
66             case R.id.text:
67                 i.putExtra("flag", "1");
68                 startActivity(i);
69                 break;
70             case R.id.image:
71                 i.putExtra("flag", "2");
72                 startActivity(i);
73                 break;
74         }
75     }
76
77     @Override
78     protected void onResume() {
79         super.onResume();
80         selectDB();
81     }
82 }

添加内容 activity

  

  1 package com.bluesky.mynote;
  2
  3 import android.app.Activity;
  4 import android.content.ContentValues;
  5 import android.content.DialogInterface;
  6 import android.content.Intent;
  7 import android.database.sqlite.SQLiteDatabase;
  8 import android.graphics.Bitmap;
  9 import android.graphics.BitmapFactory;
 10 import android.net.Uri;
 11 import android.os.Bundle;
 12 import android.os.Environment;
 13 import android.os.PersistableBundle;
 14 import android.provider.MediaStore;
 15 import android.util.Log;
 16 import android.view.Menu;
 17 import android.view.View;
 18 import android.widget.Button;
 19 import android.widget.EditText;
 20 import android.widget.ImageView;
 21 import android.widget.VideoView;
 22
 23 import java.io.File;
 24 import java.text.SimpleDateFormat;
 25 import java.util.Date;
 26
 27 /**
 28  * Created by 清晨 on 2015/5/6.
 29  */
 30 public class AddContent extends Activity implements View.OnClickListener {
 31     private NoteDB noteDB;
 32     private SQLiteDatabase dbWriter;
 33     private String flag; //接受从mainactivity传来的标识 用于判定加载不同的添加内容界面(图文或者纯文字)
 34     private EditText editText;
 35     private Button save_btn,cancel_btn;
 36     private ImageView c_img;
 37     private File imgfile;
 38     @Override
 39     public void onCreate(Bundle savedInstanceState) {
 40         super.onCreate(savedInstanceState);
 41         setContentView(R.layout.addcontent);
 42         flag=getIntent().getStringExtra("flag");
 43         initView();
 44         save_btn.setOnClickListener(this);
 45         cancel_btn.setOnClickListener(this);
 46         noteDB=new NoteDB(this);
 47         dbWriter=noteDB.getWritableDatabase();//获取写入数据库权限
 48     }
 49
 50     //初始化控件
 51     public void initView(){
 52         editText= (EditText) findViewById(R.id.ettext);
 53         save_btn= (Button) findViewById(R.id.save);
 54         cancel_btn= (Button) findViewById(R.id.cancel);
 55         c_img= (ImageView) findViewById(R.id.c_img);
 56         if(flag.equals("1")){
 57             c_img.setVisibility(View.GONE);//隐藏imageview
 58         }
 59         if(flag.equals("2")){
 60             c_img.setVisibility(View.VISIBLE);//显示imageview
 61             //启动系统相机拍照
 62             Intent getImg=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 63             //图片是放在存储卡中 路径存在数据库中 以时间命名图片 避免重名
 64             imgfile=new File(Environment.getExternalStorageDirectory()
 65                     .getAbsolutePath()+"/"+getTime()+".jpg");
 66             getImg.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imgfile));
 67             startActivityForResult(getImg,1);//便于立即查看效果
 68
 69
 70         }
 71     }
 72
 73     //获取内容并写入数据库
 74     public void addDB(){
 75         ContentValues cv=new ContentValues();
 76         cv.put(NoteDB.CONTENT,editText.getText().toString());
 77         cv.put(NoteDB.TIME,getTime());
 78         cv.put(NoteDB.PATH,imgfile + "");
 79         dbWriter.insert(NoteDB.TABLE_NAME,null,cv);
 80     }
 81
 82     //获取系统当前时间
 83     public String getTime(){
 84         SimpleDateFormat format=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
 85         Date curDate=new Date();
 86         String str=format.format(curDate);
 87         return str;
 88     }
 89
 90     @Override
 91     public void onClick(View v) {
 92         switch (v.getId()){
 93             case R.id.save:
 94                 addDB();
 95                 finish();
 96                 break;
 97             case R.id.cancel:
 98                 finish();
 99                 break;
100
101         }
102
103     }
104
105     //预览显示拍摄内容
106     @Override
107     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
108         super.onActivityResult(requestCode, resultCode, data);
109         if(resultCode==1){
110             Bitmap bitmap= BitmapFactory.decodeFile(imgfile.getAbsolutePath());
111             c_img.setImageBitmap(bitmap);
112         }
113     }
114 }

内容详情页Activity

 1 package com.bluesky.mynote;
 2
 3 import android.app.Activity;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.graphics.Bitmap;
 6 import android.graphics.BitmapFactory;
 7 import android.os.Bundle;
 8 import android.view.View;
 9 import android.widget.Button;
10 import android.widget.ImageView;
11 import android.widget.TextView;
12
13 /**
14  * Created by 清晨 on 2015/5/8.
15  */
16 public class InContent extends Activity implements View.OnClickListener {
17     private Button del_btn;
18     private Button back_btn;
19     private ImageView in_img;
20     private TextView in_tv;
21     private NoteDB noteDB;
22     private SQLiteDatabase dbWriter;
23     @Override
24     protected void onCreate(Bundle savedInstanceState) {
25         super.onCreate(savedInstanceState);
26         setContentView(R.layout.incontent);
27         initView();
28         noteDB= new NoteDB(this);
29         dbWriter=noteDB.getWritableDatabase();
30         del_btn.setOnClickListener(this);
31         back_btn.setOnClickListener(this);
32         //根据记事方式加载不同视图
33         if(getIntent().getStringExtra(NoteDB.PATH).equals("null")){
34             in_img.setVisibility(View.GONE);
35         }else {
36             in_img.setVisibility(View.VISIBLE);
37         }
38         //显示文字
39         in_tv.setText(getIntent().getStringExtra(NoteDB.CONTENT));
40         //显示图片
41         Bitmap bitmap= BitmapFactory.decodeFile(getIntent().getStringExtra(NoteDB.PATH));
42         in_img.setImageBitmap(bitmap);
43     }
44
45     public void initView(){
46         del_btn= (Button) findViewById(R.id.delete);
47         back_btn= (Button) findViewById(R.id.back);
48         in_img= (ImageView) findViewById(R.id.in_img);
49         in_tv= (TextView) findViewById(R.id.in_tv);
50     }
51
52     @Override
53     public void onClick(View v) {
54         switch (v.getId()){
55             case R.id.delete:
56                 delDB();
57                 finish();
58                 break;
59             case R.id.back:
60                 finish();
61                 break;
62         }
63     }
64     //删除数据
65     public void delDB(){
66         dbWriter.delete(NoteDB.TABLE_NAME,"id="+getIntent()
67                 .getIntExtra(NoteDB.ID,0),null);
68     }
69 }

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

时间: 2024-10-17 03:37:45

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

MVC 编程模式及其变种

MVC 编程模式及其变种 MVC的全名是Model View Controller, 是模型(model)-视图(view)-控制器(controller)的缩写,这是一种很常见的编程模型.MVC最早提出的时候是为了把数据和视图分离开来,然后用控制器作为胶水来粘合数据和实体之间的关系.这就是关注点分离的设计理念,也是单一职责原则(Single-Resposibility Principle). 在我们的开发过程中, 视图用来展现界面, 我们的模型处理业务, 持有数据, 而控制器是他们之间的中间人

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

实验二   JSP编程 一.实验目的1. 掌握JSP指令的使用方法:2. 掌握JSP动作的使用方法:3. 掌握JSP内置对象的使用方法:4. 掌握JavaBean的编程技术及使用方法:5. 掌握JSP中数据库编程方法: 二.实验要求 : 利用JSP编程技术实现一个简单的购物车程序,具体要求如下. (1)用JSP编写一个登录页面,登录信息中有用户名和密码,分别用两个按钮来提交和重置登录信息. (2)编写一个JSP程序来处理用户提交的登录信息,如果用户名为本小组成员的名字且密码为对应的学号时,采用J

jQuery 开发一个简易插件

jQuery 开发一个简易插件 //主要内容 $.changeCss = function(options){ var defaults = { color:'blue', ele:'text', fontSize:'30px' } var options = $.extend(defaults , options); var change ={ changeColor:function(){ $('#'+options.ele).css('color',options.color); }, c

python之路-利用索引切片功能做一个简易的两个未知数的加法计算器,代码如下:

python之路-利用索引切片功能做一个简易的两个未知数的加法计算器,代码如下: #content = input('请输入内容:'),如用户输入:5 +9或 5 + 9 等,然后进行分割再进行计算. content = input('>>>').strip() #content 等于所输入的内容,strip:删除字符串左右两边的空格. index = content.find('+') ''' content内容中的两边的空格都删除了,但中间还有,现在我们只需要定位已知内容是加法,两边

利用map的特性做一个简易的投票程序

pair 1. 概念:pair是 一种模版类型,每个pair 可以存储两个值,这两种值的类型无限制.也可以将自己写的struct类型的的对象放进去. 2. 用法: pair<int ,int >p (1,2); pair<int ,int > p1= make_pair(1,2); 3. 编写程序读入一系列string和int型数据,将每一组存储在一个pair对象中,然后将这些pair对象存储在vector容器并显示 #include<iostream> #includ

使用TypeScript开发一个在线记事本,支持离线存储

先贴上源码传送门: https://github.com/flowforever/yaryin.note 记事本网址: http://yindoc.com , 井号后面写你喜欢的文件名即可. 最近在研究NativeScript,NativeScript使用TypeScript,于是就顺便研究了ts. 不得不提到NativeScript源码学习,感觉学习到了不少东西,顺便也从上面扣了一个依赖注入的框架下来用,实际使用感觉非常给力. 文件地址: https://github.com/flowfore

Gof 设计模式 、MVC 编程模式

主题: Gof 设计模式 .MVC 设计模式 名词解释: OOP  (面向对象程序设计) 接口 抽象类 Refactoring(重构方法) GoF(Gang of Four),中文名——四人组.GoF是一种设计模式. via http://baike.so.com/doc/176639.html Model–view–controller (MVC) via http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller 有力

MVC编程模式

1.关于MVC ①.M:Model ②.V:View ③.C:Controller MVC是Model-View-Controller的简称,即模型-视图-控制器. MVC是一种设计模式,它把应用程序分成三个核心模块:模型.视图.控制器,它们各自处理自己的任务. 2.好处:对一个请求不使用MVC,Servlet.JSP都可以实现,但是这样的缺点就是需要在Servlet中拼写html代码,在JSP中书写处理请求的代码 MVC的处理过程 下述代码不足之处:没有使用数据库连接池.DBUtils.DAO

利用nginx和docker实现一个简易的负载均衡

测试步骤: 1.在服务器中搭建一个nginx服务器并启动,具体过程可参考 http://www.cnblogs.com/pangziyibudong/p/6183692.html,这里不在建立 2.在docker中从源中拉一下nginx的官方镜像,docker pull nginx,留着备用 3.在本地目录新建两个文件夹,我这里的新建在/mydata/test1,/mydata/test2/ 4.分别在两个test文件夹中新建index.html来标志,在第一个html中输出this is ng