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

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

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

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

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

  

   在这个案列中,一开始只是开发了添加文字内容的记事功能,添加图片功能时在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):

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

 

分别是主界面 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记下来吧.

你可能感兴趣的:(mvc)