zoukankan      html  css  js  c++  java
  • 《Android Studio实战 快速、高效地构建Android应用》--五、备忘录实验(1/2)

    • 通过开发App熟悉Android Studio的用法
    • 开发一款用于管理备忘事项列表的App,核心功能:
      • 创建、删除备忘
      • 将某些备忘标记为重要(左侧带颜色标签突出显示)
    • 涉及:操作栏菜单、上下文菜单、用于持久化的本地数据库、支持多选的设备上的多项选择

    启动新项目

    File|New|New project命名为Reminders,选择Empty Activity

    新建project

    初始化Git仓库

    安装、配置Git:https://www.cnblogs.com/hhhqqq/p/12273696.html

    • 创建Git仓库

    创建本地仓库

    然后选择项目根目录来创建Git仓库

    • 在Version Control工具窗口中右击Unversioned Files选择Add to VCS将这些文件添加到Git索引

    • 提交文件(Ctrl+K|将项目的修改记录到Git版本控制系统的过程)

      提交文件

    构建用户界面

    visual designer布局

    visual designer布局

    可视化设计器

    将左侧PaletteLegacy中的ListView拖到编辑区域放置该控件,右侧Attributes修改该控件各项属性

    listview

    编辑布局的原始XML

    单击底部Text,编辑原始XML

    编辑XML

    更改背景颜色:

     android:background="#181818"	//设置RelativeLayout背景颜色
    

    在XML布局文件中硬编码颜色值并不是最佳方案,更好的方法:在values资源文件夹下定义colors.xml,在里面定义自己的颜色。这样便于编辑而且可以很容易地在整个项目中引用。

    将代码修改为:

    	android:background="@color/dark_grey"
    

    创建颜色值资源

    在错误提示中选择第二项(创建颜色资源)

    创建颜色资源2

    修改ListView列表项的显示方式

    在reslayout文件夹中新建reminders_row,选择LinearLayout(LinearLayout是布局中的最外层元素)作为根ViewGroup来为单个列表项行创建布局,

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent"
               android:layout_height="50dp"
               android:orientation="vertical"
               android:background="@color/dark_grey">
    
     <LinearLayout
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="48dp">
    
     <view
         android:layout_width="10dp"
         android:layout_height="match_parent"
         class="android.view.View"
         android:id="@+id/row_tab"
         android:background="@color/green"/>
    
     <TextView
         android:layout_width="match_parent"
         android:layout_height="50dp"
         android:text="Reminder Text"
         android:id="@+id/row_text"
         android:textColor="@color/white"
         android:textSize="18sp"
         android:gravity="center_vertical"
         android:padding="10dp"
         android:ellipsize="end"
         android:maxLines="1"/>
    </LinearLayout>
     <view
         class="android.view.View"
         android:layout_width="fill_parent"
         android:layout_height="1dp"
         android:background="#000"/>
     <view
         class="android.view.View"
         android:layout_width="fill_parent"
         android:layout_height="1dp"
         android:background="#333"/>
    </LinearLayout>
    

    列表项完成

    向ListView添加条目

    修改相应的Activity文件(RemindersActivity.java),声明一个ListView成员、修改onCreate()方法

    private ListView mListView;
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_reminders);
         mListView = (ListView)findViewById(R.id.reminders_list_view);
         ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
                 this,   //  当前Activity的Context对象
                 R.layout.reminders_row, //使用哪个布局
                 R.id.row_text,     //布局中的哪个字段来显示数据
                 new String[]{"first record","second record"}    //示例条目
         );
         mListView.setAdapter(arrayAdapter);
     }
    

    添加条目

    添加操作栏溢出菜单

    在res文件夹下新建menu文件夹,右键New|Menu resource file命名为menu_reminders

    menu/menu_reminders.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <item android:id="@+id/action_new"
            android:title="New Reminder"
            android:orderInCategory="100"
            app:showAsAction="never"/>
        <item android:id="@+id/action_exit"
            android:title="exit"
            android:orderInCategory="200"
            app:showAsAction="never"/>
    </menu>
    

    在RemindersActivity.java中添加创建菜单的方法和菜单的点击事件

    /**
         *创建菜单
         */
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.menu_reminders,menu); //通过getMenuInflater()方法得到MenuInflater对象,再调用它的inflate()方法就可以给当前活动创建菜单了,第一个参数:用于指定我们通过哪一个资源文件来创建菜单;第二个参数:用于指定我们的菜单项将添加到哪一个Menu对象当中。
            return true; // true:允许创建的菜单显示出来,false:创建的菜单将无法显示。
        }
    
        /**
         *菜单的点击事件
         */
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
    
            switch (item.getItemId()){
                case R.id.action_new:
                    Log.d(getLocalClassName(),"create new Reminder");
                    return true;
                case R.id.action_exit:
                    finish();
                    return true;
                default:
                    return false;
            }
        }
    

    添加溢出菜单

    持久化备忘录

    • SQLite数据库
    • 数据模型、数据库代理类、CursorAdapter
      • 数据模型:保存从数据库读取以及写入数据库的数据
      • 数据库代理类:适配器类,把来自App的简单调用转换为对SQLite数据库的API调用
      • CursorAdapter:继承以抽象方式处理数据访问的标准Android类

    数据模型

    创建数据模型

    com.example.dell.reminders右键New Java Class命名为Reminder

    Reminder类:

    public class Reminder {
        private int mId;
        private String mContent;
        private int mImportant;
    
        public Reminder(int id, String content, int important) {
            mId = id;
            mContent = content;
            mImportant = important;
        }
    
        public int getId() {
            return mId;
        }
    
        public void setId(int id) {
            mId = id;
        }
    
        public String getContent() {
            return mContent;
        }
    
        public void setContent(String content) {
            mContent = content;
        }
    
        public int getImportant() {
            return mImportant;
        }
    
        public void setImportant(int important) {
            mImportant = important;
        }
    }
    

    创建数据库代理

    com.example.dell.reminders右键New Java Class命名为RemindersDbAdapter

    public class RemindersDbAdapter {
        //定义列名
        public static final String COL_ID = "_id";
        public static final String COL_CONTENT = "content";
        public static final String COL_IMPORTANT = "important";
        //定义索引值
        public static final int INDEX_ID = 0;
        public static final int INDEX_CONTENT = INDEX_ID + 1;
        public static final int INDEX_IMPORTANT = INDEX_ID + 2;
        //用于日志的TAG
        public static final String TAG = "RemindersDbAdapter";
    
        //两个数据库API对象
        private DatabaseHelper mDbHelper;
        private SQLiteDatabase mDb;
    
        //数据库名称、主表名称、版本的常量
        public static final String DATABASE_NAME = "dba_remdrs";
        public static final String TABLE_NAME = "tbl_remdrs";
        public static final int DATABASE_VERSION = 1;
    
        //上下文对象
        private final Context mCtx;
    
        //用于创建数据库的SQL语句
        private static final String DATABASE_CREATE =
                "CREATE TABLE if not exists " + TABLE_NAME + " ( " +
                        COL_ID + "INTEGER PRIMARY KEY autoincrement, " +
                        COL_CONTENT + " TEXT, " +
                        COL_IMPORTANT + " INTEGER );";
    }
    

    SQLite API

    DatabaseHelper:用于打开、关闭数据库的SQLite API类,是一个自定义的类,将其实现为RemindersDbAdapter的内部类

    private static class DatabaseHelper extends SQLiteOpenHelper{
            //构造函数完成数据库初始化
            DatabaseHelper(Context context){
                //将数据库名和版本号传给超类,由超类完成建立数据库的繁重工作
                super(context,DATABASE_NAME,null,DATABASE_VERSION);
            }
    
            public void onCreate(SQLiteDatabase db){
                Log.w(TAG,DATABASE_CREATE);
                db.execSQL(DATABASE_CREATE);
            }
    
            public void onUpgrade(SQLiteDatabase db,int oldVersion, int newVersion){
                Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");
                db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
                onCreate(db);
            }
        }
    

    使用DatabaseHelper打开和关闭数据库,RemindersDbAdapter构造函数保存了Context实例,并传给DatabaseHelper

    public RemindersDbAdapter(Context ctx) {
            this.mCtx = ctx;
        }
    
        public void open() throws SQLException{
            mDbHelper = new DatabaseHelper(mCtx);
            mDb = mDbHelper.getWritableDatabase();
        }
    
        public void close(){
            if(mDbHelper != null){
                mDbHelper.close();
            }
        }
    

    数据库的增删改查:

    创建方法使用特殊的ContentValues对象,用于将数据值传给数据库对象的insert方法,数据库会将这些对象转换为SQL insert语句并执行

    //数据库的增删改查
        public void createReminder(String name, boolean important){
            ContentValues values = new ContentValues();
            values.put(COL_CONTENT, name);
            values.put(COL_IMPORTANT, important?1:0);
            mDb.insert(TABLE_NAME,null,values);
        }
        
        public long createReminder(Reminder reminder){
            ContentValues values = new ContentValues();
            values.put(COL_CONTENT,reminder.getContent());
            values.put(COL_IMPORTANT,reminder.getImportant());
            return mDb.insert(TABLE_NAME,null,values);
        }
        
        public Reminder fetchReminderById(int id){
            Cursor cursor = mDb.query(TABLE_NAME,new String[]{COL_ID,
                    COL_CONTENT,COL_IMPORTANT},COL_ID + "=?",
                    new String[]{String.valueOf(id)},null,null,null,null);
            if(cursor != null)
                cursor.moveToFirst();
                
                return new Reminder(
                  cursor.getInt(INDEX_ID),
                  cursor.getString(INDEX_CONTENT),
                        cursor.getInt(INDEX_IMPORTANT)
                );
        }
        
        public Cursor fetchAllReminders(){
            Cursor mCursor = mDb.query(TABLE_NAME,new String[]{COL_ID,
            COL_CONTENT,COL_IMPORTANT},null,null,null,null,null);
            
            if (mCursor != null){
                mCursor.moveToFirst();
            }
            
            return mCursor;
        }
        
        public void updateReminder(Reminder reminder){
            ContentValues values = new ContentValues();
            values.put(COL_CONTENT,reminder.getContent());
            values.put(COL_IMPORTANT,reminder.getImportant());
            mDb.update(TABLE_NAME,values,
                    COL_ID+"=?",new String[]{String.valueOf(reminder.getId())});
        }
        
        public void deleteReminderById(int nId){
            mDb.delete(TABLE_NAME,COL_ID+"=?",new String[]{String.valueOf(nId)});
        }
        
        public void deleteAllReminders(){
            mDb.delete(TABLE_NAME,null,null);
        }
    

    RemindersDbAdapter最终代码

    public class RemindersDbAdapter {
        //定义列名
        public static final String COL_ID = "_id";
        public static final String COL_CONTENT = "content";
        public static final String COL_IMPORTANT = "important";
        //定义索引值
        public static final int INDEX_ID = 0;
        public static final int INDEX_CONTENT = INDEX_ID + 1;
        public static final int INDEX_IMPORTANT = INDEX_ID + 2;
        //用于日志的TAG
        public static final String TAG = "RemindersDbAdapter";
    
        //两个数据库API对象
        private DatabaseHelper mDbHelper;
        private SQLiteDatabase mDb;
    
        //数据库名称、主表名称、版本的常量
        public static final String DATABASE_NAME = "dba_remdrs";
        public static final String TABLE_NAME = "tbl_remdrs";
        public static final int DATABASE_VERSION = 1;
    
        //上下文对象
        private final Context mCtx;
    
        //用于创建数据库的SQL语句
        private static final String DATABASE_CREATE =
                "CREATE TABLE if not exists " + TABLE_NAME + " ( " +
                        COL_ID + "INTEGER PRIMARY KEY autoincrement, " +
                        COL_CONTENT + " TEXT, " +
                        COL_IMPORTANT + " INTEGER );";
    
        public RemindersDbAdapter(Context ctx) {
            this.mCtx = ctx;
        }
    
        public void open() throws SQLException{
            mDbHelper = new DatabaseHelper(mCtx);
            mDb = mDbHelper.getWritableDatabase();
        }
    
        public void close(){
            if(mDbHelper != null){
                mDbHelper.close();
            }
        }
    
        //数据库的增删改查
        public void createReminder(String name, boolean important){
            ContentValues values = new ContentValues();
            values.put(COL_CONTENT, name);
            values.put(COL_IMPORTANT, important?1:0);
            mDb.insert(TABLE_NAME,null,values);
        }
    
        public long createReminder(Reminder reminder){
            ContentValues values = new ContentValues();
            values.put(COL_CONTENT,reminder.getContent());
            values.put(COL_IMPORTANT,reminder.getImportant());
            return mDb.insert(TABLE_NAME,null,values);
        }
    
        public Reminder fetchReminderById(int id){
            Cursor cursor = mDb.query(TABLE_NAME,new String[]{COL_ID,
                    COL_CONTENT,COL_IMPORTANT},COL_ID + "=?",
                    new String[]{String.valueOf(id)},null,null,null,null);
            if(cursor != null)
                cursor.moveToFirst();
    
                return new Reminder(
                  cursor.getInt(INDEX_ID),
                  cursor.getString(INDEX_CONTENT),
                        cursor.getInt(INDEX_IMPORTANT)
                );
        }
    
        public Cursor fetchAllReminders(){
            Cursor mCursor = mDb.query(TABLE_NAME,new String[]{COL_ID,
            COL_CONTENT,COL_IMPORTANT},null,null,null,null,null);
    
            if (mCursor != null){
                mCursor.moveToFirst();
            }
    
            return mCursor;
        }
    
        public void updateReminder(Reminder reminder){
            ContentValues values = new ContentValues();
            values.put(COL_CONTENT,reminder.getContent());
            values.put(COL_IMPORTANT,reminder.getImportant());
            mDb.update(TABLE_NAME,values,
                    COL_ID+"=?",new String[]{String.valueOf(reminder.getId())});
        }
    
        public void deleteReminderById(int nId){
            mDb.delete(TABLE_NAME,COL_ID+"=?",new String[]{String.valueOf(nId)});
        }
    
        public void deleteAllReminders(){
            mDb.delete(TABLE_NAME,null,null);
        }
        
        private static class DatabaseHelper extends SQLiteOpenHelper{
            //构造函数完成数据库初始化
            DatabaseHelper(Context context){
                //将数据库名和版本号传给超类,由超类完成建立数据库的繁重工作
                super(context,DATABASE_NAME,null,DATABASE_VERSION);
            }
    
            public void onCreate(SQLiteDatabase db){
                Log.w(TAG,DATABASE_CREATE);
                db.execSQL(DATABASE_CREATE);
            }
    
            public void onUpgrade(SQLiteDatabase db,int oldVersion, int newVersion){
                Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");
                db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
                onCreate(db);
            }
        }
    }
    

    CursorAdapter

    最后,需要一种从数据库获取备忘并加入到ListView中的方法,新建java类RemindersSimpleCursorAdapter

    public class RemindersSimpleCursorAdapter extends SimpleCursorAdapter {
        public RemindersSimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
            super(context, layout, c, from, to, flags);
        }
    
        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            return super.newView(context, cursor, parent);
        }
    
    
        //ListView会利用屏幕上的单个View对象反复调用此方法,Adapter的职责就是使用列表项来填充这些视图
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            super.bindView(view, context, cursor);//调用超类方法,通过游标cursor获取到的值映射到View中的元素
    
            ViewHolder holder = (ViewHolder)view.getTag();
            if(holder == null){ //检查holder是否绑定到了标签
                holder = new ViewHolder();
                holder.colImp = cursor.getColumnIndexOrThrow(RemindersDbAdapter.COL_IMPORTANT);
                holder.listTab = view.findViewById(R.id.row_tab);
                view.setTag(holder);
            }
    
            //使用当前备忘COL_IMPORTANT常量对应的值来决定颜色1:重要 0:次要
            if(cursor.getInt(holder.colImp) > 0){
                holder.listTab.setBackgroundColor(context.getResources().getColor(R.color.orange));
            }
            else{
                holder.listTab.setBackgroundColor(context.getResources().getColor(R.color.green));
            }
        }
    
        //静态内部类
        static class ViewHolder{
            int colImp; //Important表列的索引
            View listTab;   //在布局中定义的row_tab视图
        }
    }
    

    调整ReminderActivity

    public class RemindersActivity extends AppCompatActivity {
    
        private ListView mListView;
        private RemindersDbAdapter mDbAdapter;
        private RemindersSimpleCursorAdapter mCursorAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_reminders);
            mListView = (ListView)findViewById(R.id.reminders_list_view);
            mListView.setDivider(null);
            mDbAdapter = new RemindersDbAdapter(this);
            mDbAdapter.open();
    
            Cursor cursor = mDbAdapter.fetchAllReminders();
    
            String[] from = new String[]{RemindersDbAdapter.COL_CONTENT};
    
            int[] to = new int[]{R.id.row_text};
    
            mCursorAdapter = new RemindersSimpleCursorAdapter(
                    RemindersActivity.this,
                    R.layout.reminders_row,
                    cursor,
                    from,
                    to,
                    0
            );
            mListView.setAdapter(mCursorAdapter);
        }
    }
    

    调整完运行app,将不会在列表中看到任何内容,因为最后的修改插入的是SQLite功能而非示例数据

    part1最后

    Ctrl+K提交备忘录实验1的最后一次修改

    最后提交

  • 相关阅读:
    linux下18种监测网络带宽方式
    python常用正则表达式
    python获取当前路径
    python获取本机的IP
    Linux 误卸载自带python后的解决办法
    jmeter分布式运行
    jmeter非GUI的运行命令
    linux下安装jmeter
    java基础笔记(8)
    java基础笔记(7)
  • 原文地址:https://www.cnblogs.com/hhhqqq/p/12273743.html
Copyright © 2011-2022 走看看