利用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记下来吧.

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。