Activity学习日记(四)

                               Activity学习日记(四)

主要内容:数据存储
        SharePreference
        文件存储:
                内部存储
                外部存储
        数据库存储
-----------------------------------------------------------------------
简单介绍:
            无论是什么平台,开发环境,数据都是核心,对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会
            有很大的促进作用,总体的来讲,数据存储方式有三种:
                            1,文件
                                    文件用起来较为方便,程序可以自己定义格式
                            2,数据库
                                    在海量数据时性能优越,有查询功能,可以加密,可以加锁,可以跨应用,跨平台等等
                            3 , 网络
                                    可以实时采集到的数据需要马上通过网络传输到数据处理中心进行存储并进行处理。
            Android平台中实现数据存储的5种方式:
                    1 使用SharedPreferences存储数据;  
                    2 文件存储数据
                    3 SQLite数据库存储数据;
                    4 网络存储数据;
                    这几种方式各自有各自的优点和缺点,要根据不同的实际情况来选择,而无法给出统一的标准
                
                    1.SharedPreferences共享偏好 
                    2.Internal Storage内部存储空间 
                    3.External Storage外部存储空间 
                    4.SQLite Database数据库 
                    5.Internet网络 
            数据存放路径:
                    SharedPreferences
                        /data/data/packagename/Shared_Pref
                    File
                        /data/data/PackageName/files
                    SQLite数据库
                        /data/data/Package Name/database
-----------------------------------------------------------------------------------
Shared Preferences:共享偏好(设置)
        很多软件会有配置文件,里面存放这程序运行当中的各个属性值,由于其配置信息并不多,如果采用数据库来存放并不划算,因为数据库连接跟
        操作等耗时大大影响了程序的效率,因此我们使用键值这种一一对应的关系来存放这些配置信息。SharedPreferences正是Android中用于实现
        这中存储方式的技术
                        1,是用来存储一些Key/Value类似的成对的基本数据类型,注意,它只能存储基本数据类型,也即int, long, boolean, String, float
                            事实上它完全相当于一个HashMap,唯一不同的就是HashMap中的Value可以是任何对象,而SharedPreferences中的值只能存储
                            基本数据类型(primitive types)。
                        2, 所有的保存的配置都会保存在xml文件中,文件在保存在/data/data/packagename/Shared_Pref
                        3,最适合SharedPreferences的地方就是保存配置信息,因为很多配置信息都是Key/Value,在Android当中SharedPreferences使用
                            最多的地方也是用来保存配置(Settings)信息,比如系统设置,登录界面的密码保存,状态保存, 各个应用中的Settings等等
                        4,如果要保存非基本数据类型也可以,只是需要进行处理,比如
                                a,如果要保存一个数组,可以把数据进行处理,把它转化成一个String,取出的时候再还原就好了
                                b,如果要保存一个对象,可以把对象序列化成为字符序列,或转成String(Object.toString()),
                                            或是把它的HashCode(Object.hashCode())当成Value保存进去
                        
                    
            SharedPreferences常用的属性和方法:
                        public abstract boolean contains (String key)
                                    判断SharedPreferences是否包含特定key的数据
                        public abstract SharedPreferences.Editor edit ()
                                    返回一个Edit对象用于操作SharedPreferences
                        public abstract Map<String, ?> getAll ()
                                    获取SharedPreferences数据里全部的key-value对
                        getXXX(String key,XXX defvlaue)
                                    获取SharedPreferences数据指定key所对应的value,如果该key不存在,返回默认值defValue
                                    其中XXX可以是boolean、float、int、long、String等基本类型的值
                        由于SharedPreference是一个接口,而且在这个接口里并没有提供写入数据和读取数据的能力
                        但是在其内部有一个Editor内部的接口,Edit这个接口有一系列的方法用于操作SharedPreference

                        Editor接口的常用方法(主要是写和清除,读的话,直接用SharedPreferences的接口)
                                public abstract SharedPreferences.Editor clear ()
                                        清空SharedPreferences里所有的数据
                                public abstract boolean commit ()
                                        当Editor编辑完成后,调用该方法可以提交修改,而且必须要调用这个数据才修改
                                public abstract SharedPreferences.Editor putXXX (String key, boolean XXX)
                                        向SharedPreferences存入指定的key对应的数据,其中XXX可以是boolean、float、int、long、String等基本类型的值
                                public abstract SharedPreferences.Editor remove (String key)
                                        删除SharedPreferences里指定key对应的数据项

            使用SharedPreferences保存key-value对的步骤如下:
                      (1)使用Activity类的getSharedPreferences方法获得SharedPreferences对象,其中存储key-value的文件的名称
                                由getSharedPreferences方法的第一个参数指定。
                      (2)使用SharedPreferences接口的edit获得SharedPreferences.Editor对象。
                      (3)通过SharedPreferences.Editor接口的putXxx方法保存key-value对。其中Xxx表示不同的数据类型。例如:
                                字符串类型的value需要用putString方法。
                      (4)通过SharedPreferences.Editor接口的commit方法保存key-value对。commit方法相当于数据库事务中的提交
                                (commit)操作。
            回顾总结:
                        1、  如何得到SharedPreferences
                                SharedPreferences preferences=getPreferences(“test”,MODE_PRIVATE);
                        2、  如何编辑SharedPreferences
                                    得到Editor对象实例
                                    SharedPreferences.Editor editor=preferences.editor();
                        3、  SharedPreferences的存储位置
                                /data/data/<package name>/shared_prefs

    sharedPreferences = getSharedPreferences("test", Context.MODE_PRIVATE);
        //如果要编辑xml文件,就必须有一个editor对象
        editor = sharedPreferences.edit();
        
        //往xml文件中写键值对
        editor.putBoolean("isAuto", false);
        editor.putBoolean("isMark", true);
        editor.putString("username", "root");
        
        
        //提交
        editor.commit();
        
        //将数据读出来
        boolean  isMark = sharedPreferences.getBoolean("isMark", false);
        Log.d(TAG, "isMark = " + isMark);
        
        Map<String, ?> mapData =  sharedPreferences.getAll();
        //一次性全部将数据读出来
        for(Map.Entry<String, ?> entry : mapData.entrySet()){
            String key = entry.getKey();
            Object value = mapData.get(key);
            
            Log.d(TAG, "key = " + key + " value = " + value);
        }
        ---------------------------------------------------------------------------------------------------------------------------
        文件存储数据:
                    在Android中读取/写入文件的方法,与 Java中实现I/O的程序是完全一样的,提供了openFileInput()
                    和openFileOutput()方法来读取设备上的文件,一般根据文件的存储方式,分为内部和外部存储方式
                
                    内部存储:
                        以这种方式创建的文件只能被该当前程序访问,不可被其他程序或用户访问,当用户卸载该程序的时候,
                        这些文件也随之被删除,当然如果要完全保证文件不会被其他应用访问,必须有合适创建模式(MODE_PRIVATE)来完成权限控制
                        避免使用MODE_WORLD_WRITEABLE和MODE_WORLD_READABLE模式创建进程间通信的内部存储

                        Context为我们提供了以下的几个方法
                                FileInputStream openFileInput(String name)
                                        打开应用程序的数据文件夹下的name文件对应的输入流
                                FileOutputStream openFileOutput(String name,int mode)
                                        打开应用程序的数据文件夹下的name文件对应的输出流,并且指定以某种方式打开。

                                getDir(String name,int mode)
                                        在应用程序的数据文件下获取或创建name对应的子目录
                                File getFilesDir()
                                        得到该应用程序数据文件夹的绝对路径
                                String[] fileList()
                                        等到该应用程序数据文件夹下的全部文件
                                deleteFile(String name)
                                        删除该应用程序的数据文件夹下的指定文件

                        内部存储的编程方式:根据google的api文档;
                                1, 调用openFileOutput() ,返回FileOutputStream.
                                2,使用write()写文件
                                3,使用read()读文件
                                4,close()
                                例子:
                                        String FILENAME = "hello_file";
                                        String string = "hello world!";

                                        FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
                                        fos.write(string.getBytes());
                                        fos.close();
                                现象:会在/data/data/PackageName/files目录下,出现hello_file文件


                缓存(cache)
                        cache files的操作与操作内部存储中的文件方式基本一致,只是获取文件的路径有说不同。如果需要使用缓存的方式进行数据持久话,
                        那么需要使用Context.getCacheDir()方法获取文件保存的路径。对于缓存文件而言,当设备内部内存存储空间不足的时候,Android
                        会有自动删除的机制删除这些缓存文件,用来恢复可用空间,所以对于缓存文件而言,内容一般最好控制在1MB之下,并且也不要存
                        放重要的数据,因为很可能下次去取数据的时候,已经被Android系统自动清理了。


              外部存储方式:
                            一般android设备都支持外接存储介质,  比如SD卡或者是内部存储分出的用于外部存储的分区上,外部存储就是将数据文件保存在
                            这些存储介质中,通过usb连接到pc之后,手机作为mass storage,用户可以直接访问这里的文件
                            使用sdcard存储的数据,不限制只有本应用访问,任何可以有访问Sdcard权限的应用均可以访问,而Sdcard相对于设备的内部存储
                            空间而言,会大很多,所以一般比较大的数据,均会存放在外部存储中。而在代码操作中我们会用到Environment这个类

                            Environmet类
                                常用常量:
                                    String MEDIA_MOUNTED
                                            当前Android的外部存储器可读可写
                                    String MEDIA_MOUNTED_READ_ONLY
                                            当前Android的外部存储器只读
                                常用方法:
                                        public static File getDataDirectory ()
                                                    获得Android下的data文件夹的目录
                                        public static File getDownloadCacheDirectory ()
                                                    获得Android Download/Cache 内容的目录
                                        public static File getExternalStorageDirectory ()
                                                    获得Android外部存储器也就是SDCard的目录
                                        public static String getExternalStorageState ()
                                                    获得Android外部存储器的当前状态
                                        public static File getRootDirectory ()
                                                    获得Android下的root文件夹的目录
                                    

                            要想实现对SDCard的读取操作,只需要按以下几个步骤就行
                                1、  先判断这台手机设备上是否有SDCard且具有读写SDCard的权限    
                                            Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
                                2、  既然转向了Sdcard,那么存储的文件路径就需要相对变更,使用Envir.getExternalStorageDirectory()方法获取当Sdcard的根目录,
                                        可以通过它访问到相应的文件

                                3、  使用IO流对外部存储器进行文件的读写

                                4、  别忘记了要在AndroidMainfest.xml中添加权限
                                        <!-- 在SDCard中创建与删除文件权限 -->  
                                        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  
                                        <!-- 往SDCard中写入数据权限 -->        
                                        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  

                            简单的示例代码:
                                public void saveToSdcard(String filename, String content) throws IOException {
                                         final String state = Environment.getExternalStorageState();
                                          if (state.equals(Environment.MEDIA_MOUNTED) || state.equals(Environment.MEDIA_READ_ONLY)) {
                                                    Log.i("main", "本设备有存储卡!");
                                                    File file = new File(Environment.getExternalStorageDirectory(),  filename);
                                                    FileOutputStream fos = null;
                                                    fos = new FileOutputStream(file);
                                                    fos.write(content.getBytes());
                                                    fos.close();
                                     }
                                 }
                                 实际效果(模拟器中):在/mnt/sdcard/目录下会自动产生一个文件
                        

                        常见的文件夹访问:
                                
                                /data
                                        Environment.getDataDirectory(): 
                                /storage/sdcard0  或者是在模拟器上: /mnt/sdcard
                                            Environment.getExternalStorageDirectory():    
                                /storage/sdcard0/dir1
                                            Environment.getExternalStoragePublicDirectory("dir1");
                                            Environment.getExternalStoragePublicDirectory(Environment.Music);
                                            Context.getExternalFilesDir("")
                                            Context.getExternalFilesDir("file1")
                                            Context.getExternalFilesDir(Environment.Music);
                                            Context.getExternalFilesDir(Environment.Picture);

                                        

            File file1 = Environment.getDataDirectory();
            Log.i(TAG, "path = " + file1.getAbsolutePath());
            File file2 = Environment.getExternalStorageDirectory();
            Log.i(TAG, "path = " + file2.getAbsolutePath());
            File file3 = Environment.getRootDirectory();
            Log.i(TAG, "path = " + file3.getAbsolutePath());
            File file4 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            Log.i(TAG, "path = " + file4.getAbsolutePath());
            file4= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
            Log.i(TAG, "path = " + file4.getAbsolutePath());
            file4 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
            Log.i(TAG, "path = " + file4.getAbsolutePath());
            file4 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            Log.i(TAG, "path = " + file4.getAbsolutePath());
            file4 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
            Log.i(TAG, "path = " + file4.getAbsolutePath());
            
            File file5 = getExternalFilesDir("ex_test");
            Log.i(TAG, "file 5 path = " + file5.getAbsolutePath());

            09-08 07:10:29.725: I/InternalFileDemo(2285): state = mounted
            09-08 07:10:29.725: I/InternalFileDemo(2285): path = /data
            09-08 07:10:29.745: I/InternalFileDemo(2285): path = /mnt/sdcard
            09-08 07:10:29.745: I/InternalFileDemo(2285): path = /system
            09-08 07:10:29.745: I/InternalFileDemo(2285): path = /mnt/sdcard/DCIM
            09-08 07:10:29.775: I/InternalFileDemo(2285): path = /mnt/sdcard/Download
            09-08 07:10:29.775: I/InternalFileDemo(2285): path = /mnt/sdcard/Music
            09-08 07:10:29.775: I/InternalFileDemo(2285): path = /mnt/sdcard/Pictures
            09-08 07:10:29.775: I/InternalFileDemo(2285): path = /mnt/sdcard/Movies
            09-08 07:10:29.785: I/InternalFileDemo(2285): file 5 path = /mnt/sdcard/Android/data/com.example.data.fileinternal/files/ex_test

            ---------------------------------------------------------------------------------------------------------------------------
            SQLite数据库存储:
                在Android平台上,集成了一个嵌入式关系型数据库—SQLite,SQLite3。因此中我们可以选择使用SQLite数据库存储数据
                SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它占用资源非常的低,在嵌入式设备中,可能只需要
                几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合
                同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快
                
                SQLite是一种转为嵌入式设备设计的轻型数据库,其只有五种数据类型,分别是:
                        NULL: 空值
                        INTEGER: 整数
                        REAL: 浮点数
                        TEXT: 字符串
                        BLOB: 二进制数据
                SQLite常用命令:
                        sqlite3 test.db 创建数据库
                        .databases  查看已有数据库
                        .help
                        .CREATE TABLE person (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER); 
                        .tables  查看已有的表
                        .schema person  查看表的结构,如果后面没有表名做参数,则将会输出所有表的建表语句
                SQLite语句复习:
                        DROP TABLE IF EXISTS tab   如果表tab存在,那就删除
                        create table tab(_id INTEGER PRIMARY KEY AUTOINCREMENT, age INTEGER, name TEXT NOT NULL)
                        
                        查询语句:select * from 表名 where 条件子句 group by 分组字句 having ... order by 排序子句
                        如:select  *  from person
                                select  *  from person order by id desc
                        分页SQL与mysql类似,下面SQL语句获取5条记录,跳过前面3条记录
                                select * from Account limit 5 offset 3 或者 select * from Account limit 3,5
                        插入语句:insert into 表名(字段列表) values(值列表)。如: insert into person(name, age) values (NULL‘张三’,3)
                                        INSERT INTO Persons VALUES ('Gates', 'Bill', 'Xuanwumen 10', 'Beijing')
                        更新语句:update 表名 set 字段名=值 where 条件子句。如:update person set name =‘张三‘ where id = 10
                        删除语句:delete from 表名 where 条件子句。如:delete from person  where id=10
                                        DELETE FROM table_name
            
            重要的类:
                    SQLiteDatabase : 代表一个数据库(底层就是一个数据库文件)
                    Cursor:一个游标,可以理解为一个对数据库操作之后的结果集, 比如可以通过它遍历所有的数据库项
            
        在Android系统中提供了android.database.sqlite包,用于进行SQLite数据库的增、删、改、查工作。SQLiteDatabase主要方法如下:
      beginTransaction(): 开始一个事务。
      close(): 关闭连接,释放资源。
      delete(String table, String whereClause, String[] whereArgs): 根据给定条件,删除符合条件的记录。
      endTransaction(): 结束一个事务。
      execSQL(String sql): 执行给定SQL语句。
      insert(String table, String nullColumnHack, ContentValues values): 根据给定条件,插入一条记录。
      openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory): 根据给定条件连接数据库,如果此数据库不存在,则创建。
      query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy): 执行查询。
      rawQuery(String sql, String[] selectionArgs): 根据给定SQL,执行查询。
      update(String table, ContentValues values, String whereClause, String[] whereArgs): 根据给定条件,修改符合条件的记录。
      除了上诉主要方法外,Android还提供了诸多实用的方法,总之一句话:其实Android访问数据库是一件很方便的事儿。

    通过两种方式去操作数据库:
    1,通用的接口:
           execSQL(String sql):
    2,数据库对象中封装了相应的方法:
            insert();  ==>
                    ContentValues values = new ContentValues();
                    values.put("age", 55);
                    values.put("name", "习大大");
                    insert("person",  null, values );
                    --> execSQL("insert into person values (NULL,  bill,  34)");
            query("person",);  ---> execSQL("select * from person ");
                query("person", null, null, null, null, null, null);
                rawQuery("select * from person  where age > ?",  new String[]{"10"});
            upate();
                    -->execSQL("update person set   age =  10  where  name = 习大大 " );
                    -->  
                            ContentValues values = new ContentValues();
                            value.put("age", 10);
                            update("person",  values,  "name = ?  " ,  new String[]{"习大大"} );
            delete()
                    delete("person",  "id = ?" , new String[]{"4"});

    1.创建数据库
      通过openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)方法创建数据库。    
            //方法一
            SQLiteDatabase db =Context.this.openOrCreateDatabase("test_db.db", Context.MODE_PRIVATE, null);//
            //方法二
            SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase("/data/data/com.test/databases/test_db2.db3", null);
      如上两种方式均能创建数据库,this.openOrCreateDatabase是对SQLiteDatabase.openOrCreateDatabase而来,如代码所见,
        原生的SQLiteDatabase.openOrCreateDatabase()方法第一参数要求输入绝对路劲,而所有的数据库都是储存于
    “data/data/应用包名/databases”目录下,所以输入完全的绝对路劲是一件重复且繁杂的工作。采用this.openOrCreateDatabase则省去了此操作。
        另外还可以通过写一个继承SQLiteOpenHelper类的方式创建数据库,此种方式是一种更加进阶的创建方式。后面专门介绍

    2、创建数据表,插入数据
      Android系统并没有提供特别的创建数据表的方法,数据表通过SQL语句创建,代码如下:
            db.execSQL("create table tab(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
        表创建好之后,通过insert(String table, String nullColumnHack, ContentValues values)方法插入数据,其中参数含义分别为:
        table: 目标表名
            nullColumnHack: 指定表中的某列列名。因为在SQLite中,不允许插入所有列均为null的记录,因此初始值有值为空时,此列需显式赋予null
        values: ContentValues对象,类似于java中的Map。以键值对的方式保存数据。
         数据插入代码如下: 
            ContentValues values =new ContentValues();
            for(int i=0;i<10;i++){
                values.put("name", "test"+ i);
                db.insert("tab", "_id", values);
            }

    3、修改数据
        update(String table, ContentValues values, String whereClause, String[] whereArgs)方法用于修改数据,其四个参数的具体含义如下:
        table: 目标表名
        values: 要被修改成为的新值
        whereClause: where子句,除去where关键字剩下的部分,其中可带?占位符。如没有子句,则为null。
        whereArgs: 用于替代whereClause参数中?占位符的参数。如不需传入参数,则为null。
      数据修改代码如下:
            ContentValues values =new ContentValues();
            values.put("name", "name");
            db.update("tab", values, "_id=1", null);
            db.update("tab", values, "_id=?", new String[]{"5"});
             _id=1和_id=5的数据,name字段的值被修改为了“name”。

    4、查询数据。
        之前一直使用SQLite客户端查看数据情况了,这里就使用android提供的query()和rawQuery()方法执行查询。具体代码如下:
            Cursor c = db.query("tab", null, null, null, null, null, null);
            //  Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
            // 调用SQLiteDatabase对象的query方法进行查询,返回一个Cursor对象:由数据库查询返回的结果集对象  
            // 第一个参数String:表名  
            // 第二个参数String[]:要查询的列名  
            // 第三个参数String:查询条件  
            // 第四个参数String[]:查询条件的参数  
            // 第五个参数String:对查询的结果进行分组  
            // 第六个参数String:对分组的结果进行限制  
            // 第七个参数String:对查询的结果进行排序  
            c.moveToFirst();
            while(!c.isAfterLast()){
                int index = c.getColumnIndex("name");
                Log.d("SQLite", c.getString(index));
                c.moveToNext();
            }
            
            c = db.rawQuery("select * from tab", null);
            c.moveToFirst();
            while(!c.isAfterLast()){
                int index = c.getColumnIndex("name");
                Log.d("SQLite", c.getString(index));
                c.moveToNext();
            }

        query和rawQuery方法在的不同仅仅在于所需参数的不同。rawQuery方法需要开发者手动写出查询SQL,而query方法是由目标表名、where子句、order by子句、having子句等诸多子句由系统组成SQL语句。两方法同返回Cursor对象,所以两方在使用时孰优孰劣,就看具体情况了。本人更喜欢rawQuery的方式,因为此方式更接近传统Java开发,也可以由专业DBA来书写SQL语句,这样更符合MVC的思想,而且这样的代码可读性更高。(query方法里面参数实在太多,有点记不住谁是order by子句,谁是having子句了)
        
        Cursor对象可以理解为游标对象,凡是对数据有所了解的人,相信对此对象都不会陌生,在这里机不再累述。只提醒一点,在第一次读取Cursor对象中的数据时,一定要先移动游标,否则此游标的位置在第一条记录之前,会引发异常。
        下面是Cursor对象的常用方法:
            c.move(int offset); //以当前位置为参考,移动到指定行  
            c.moveToFirst();    //移动到第一行  
            c.moveToLast();     //移动到最后一行  
            c.moveToPosition(int position); //移动到指定行  
            c.moveToPrevious(); //移动到前一行  
            c.moveToNext();     //移动到下一行  
            c.isFirst();        //是否指向第一条  
            c.isLast();     //是否指向最后一条  
            c.isBeforeFirst();  //是否指向第一条之前  
            c.isAfterLast();    //是否指向最后一条之后  
            c.isNull(int columnIndex);  //指定列是否为空(列基数为0)  
            c.isClosed();       //游标是否已关闭  
            c.getCount();       //总数据项数  
            c.getPosition();    //返回当前游标所指向的行数  
            c.getColumnIndex(String columnName);//返回某列名对应的列索引值  
        
            c.getString(int columnIndex);   //返回当前行指定列的值  
            c.getInt(int columnIndex);   //返回当前行指定列的值 

    5、删除数据
        删除数据也是一件很简单的事,只需要调用delete方法,传入参数即可,delete(String table, String whereClause, String[] whereArgs)的参数三个参数具体含义如下:
        table: 目标表名
        whereClause: where子句,除去where关键字剩下的部分,其中可带?占位符。如没有子句,则为null。
        whereArgs: 用于替代whereClause参数中?占位符的参数。如不需传入参数,则为null。
      具体代码如下:
            db.delete("tab", "_id=? or name=?", new String[]{"8", "baiyun"});
        
        其中_id=8和name=‘baiyun’的数据统统被删除了。    
        整个数据库的CRUD操作到此演示完了。最后提醒一点,在操作完数据后,一定要记得调用close()方法关闭连接,释放资源。
    上面就是SQLite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自    SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。

--------------------------------------------------------------------------------------------------------------------------------

  • 理解Activity的生命周期_intent和intent-filter
package com.hq.myapp;



import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;


public class LoginActivity extends Activity {
	private final String TAG = "MyApp";
	Button  btn_login;
	Button  btn_exit;
	EditText et_username;
	EditText et_passwd;
	
	
	void myToast()
	{
		//来个吐司--用于调试/提示
		//自定义一个吐司
		Toast t = Toast.makeText(LoginActivity.this, "自定义吐司", Toast.LENGTH_SHORT);
		t.setGravity(Gravity.CENTER, 0, 0);
		LinearLayout layout = 	(LinearLayout) t.getView();  //得到一个view
		ImageView image = new ImageView(LoginActivity.this);
		image.setImageResource(R.drawable.head3);
		layout.addView(image);
		t.show();
	}
	
	//必须有一个监听器
	OnClickListener btnClickListener = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			Log.d(TAG, "点击了,666");
			
			// 1,获取两个输入框的内容
			String username = et_username.getText().toString().trim();
			String passwd = et_passwd.getText().toString().trim();
			// 2, 比对内容
			if(!username.isEmpty() && !passwd.isEmpty()){
				if(username.equals("root") && passwd.equals("123456")){
					myToast();
					// 3, 比对密码成功就进入另外一个界面xxx.class是所有类中一个程序,记录对应类的信息
					
					/*
					// 第一种启动方式--显示启动
					Intent  intent = new Intent(LoginActivity.this, RegiterActivity.class);
					startActivity(intent);
					*/
					
					//第二种启动方式---隐式启动
					Intent intent = new Intent(); //已经加了默认的分类
					intent.setAction("com.hq.test.action");
					intent.addCategory(Intent.CATEGORY_DEFAULT);
					intent.addCategory("com.hq.my.cateroy");
					intent.setData(Uri.parse("MyData://my.host/10010"));
					startActivity(intent);
					
				}else{
					Toast.makeText(LoginActivity.this, "用户或者密码错误", 1000).show();
				}
				
				
			}else{
				Toast.makeText(LoginActivity.this, "用户或者密码不能为空", 1000).show();
			}
			
			
			
			
		}
	}; 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		//其实该代码已经对xml中所有的标签进行分析,已经new所有控件
		setContentView(R.layout.activity_login);
		
		initUI();
		
	}
	private void initUI() {
		// TODO Auto-generated method stub
		
		et_passwd = (EditText) findViewById(R.id.et_passwd);
		et_username = (EditText) findViewById(R.id.et_username);
		
		//获取到ui控件
		btn_login = (Button) findViewById(R.id.btn_login);
		//绑定事件源和监听器
		btn_login.setOnClickListener(btnClickListener);
		
		btn_exit = (Button) findViewById(R.id.btn_exit);
		btn_exit.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				
				// 先要创造建造工--创建dialog对象的对象
				AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
				//设置icon图标
				builder.setIcon(R.drawable.button_share);
				//设置标题栏
				builder.setTitle("退出对话框");
				// 设置消息体
				builder.setMessage("你真的那么忍心就退出吗");
				// 设置两个按钮
				builder.setNegativeButton("再玩会", null);
				builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						System.exit(1);
					}
				});
				//创造对话框
				builder.create().show();
				
			}
		});
	}

	
}
package com.hq.myapp;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class RegiterActivity extends Activity{
	private final String TAG = "MyApp";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_register);
		
		Log.d(TAG, "----------onCreate()------------");
		
	}
	
	
	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Log.d(TAG, "----------onStart()------------");
		
	}
	
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.d(TAG, "----------onResume()------------");
	}
	
	
	@Override
	protected void onRestart() {
		// TODO Auto-generated method stub
		super.onRestart();
		Log.d(TAG, "----------onRestart()------------");
	}
	
	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		Log.d(TAG, "----------onPause()------------");
	}
	
	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		Log.d(TAG, "----------onStop()------------");
	}
	
	
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		
		Log.d(TAG, "----------onDestroy()------------");
	}
}
package com.hq.myapp;

import android.app.Activity;
import android.os.Bundle;

public class ThirdActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.acitivy_third);
	}
	
	
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_user_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="18dp"
        android:layout_marginTop="34dp"
        android:text="用户名"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <EditText
        android:id="@+id/et_username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tv_user_name"
        android:layout_alignBottom="@+id/tv_user_name"
      	android:layout_toRightOf="@id/tv_user_name"
        android:layout_marginLeft="30dp"
        android:ems="10"
        android:inputType="textPersonName" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/tv_passwd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_user_name"
        android:layout_below="@+id/tv_user_name"
        android:layout_marginTop="59dp"
        android:text="密  码"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <EditText
        android:id="@+id/et_passwd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/tv_passwd"
        android:layout_alignLeft="@+id/et_username"
        android:ems="10"
        android:inputType="textPassword" />

    <CheckBox
        android:id="@+id/cb_mark_pwd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_passwd"
        android:layout_centerVertical="true"
        android:text="记住密码" />

    <CheckBox
        android:id="@+id/cb_auto_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/cb_mark_pwd"
        android:layout_marginLeft="45dp"
        android:layout_toRightOf="@+id/cb_mark_pwd"
        android:text="自动登录" />

    <Button
        android:id="@+id/btn_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/cb_mark_pwd"
        android:layout_below="@+id/cb_mark_pwd"
        android:layout_marginTop="67dp"
        android:text="登录" />

    <Button
        android:id="@+id/btn_exit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/btn_login"
        android:layout_alignRight="@+id/et_username"
        android:layout_marginRight="16dp"
        android:text="退出" />

</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RatingBar
        android:id="@+id/ratingBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="86dp" />

</RelativeLayout>
<?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="match_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/editText1"
        android:hint="输入文字"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" >

        <requestFocus />
    </EditText>

</LinearLayout>

猜你喜欢

转载自blog.csdn.net/weixin_42471952/article/details/81114630
今日推荐