zoukankan      html  css  js  c++  java
  • 利用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记下来吧.

  • 相关阅读:
    把Linux安装到移动硬盘上
    关于thinkphp 开发的网站部署问题
    lamp 网站打不开,不显示也不报错,
    前端之css语法3
    前端之css笔记2
    前端之练习2
    前端之css笔记1
    前端之笔记1
    前端之练习1
    MySQL之练习题5
  • 原文地址:https://www.cnblogs.com/morningsky/p/4490778.html
Copyright © 2011-2022 走看看