Android数据存储的五种方式

一、Share Preferences共享参数(存储基本数据类型)---私有的
    共享参数的存储地址:data/data/应用程序包名/shared_prefs/文件名.xml
    1、是用键值对<Key, Value>的形式来存储数据的。当再次启动程序后依然保持原有设置。
    2、目前支持String、int、long、float、boolean等基本类型的存储,对于自定义的对象数据类型,无法使用    SharedPreferences来存储。
    3、SharedPreferences主要用于存储系统的配置信息。例如上次登录的用户名上次最后设置的配置信息
         像JSON字符串这种大数据和复杂数据就不用SharedPreferences来存储。
      使用SharedPreferences的步骤
        (1) 获取SharedPreferences对象
        (2) 调用edit()方法获取SharedPreferences.Editor
        (3) 通过SharedPreferences.Editor接口提供的put()方法对SharedPreferences进行更新
        (4) 调用SharedPreferences.Editor的commit()方法,将更新提交到SharedPreferences中
    存储数据
        //参数含义---存储的文件名(可以不用写后缀名,会自动添加.xml)  
        //操作模式:一般使用私有模式(也是默认的)
        SharedPreferences sp = getSharedPreferences("first", MODE_PRIVATE);
        Editor edit = sp.edit();
        edit.putString("s", "存储的字符串");
        edit.commit();     //提交数据
        // edit.clear();    //清空以前存储的数据(把key值得节点都清除掉)

    读取数据
       //读取存在的文件(一般存数据与取数据不放在同一个类中,所以就把文件名提出来放在常量类中)
        String s = sp.getString("s", "默认值");

二.1、Internal Storage内部存储(存储文件)---私有的
        FileInputStreamFileOutputStream对文件进行读和写
      写的路径和读的路径是一致的
        路径:data/data/当前项目的包名/文件名.后缀名
        File file = new File("data/data/com.shirly.day13innerstoragedemo/first.txt");
        路径:data/data/当前项目的包名/files/文件名.后缀名
        File file = new File(getFilesDir(), "second.txt");
        路径:data/data/当前项目的包名/cache/文件名.后缀名
        File file = new File(getCacheDir(), "third.txt");    //写入缓存文件
        路径:data/data/当前项目的包名/files/文件名.后缀名
        FileOutputStream fos = openFileOutput("fourth.txt", MODE_PRIVATE);

二.2、External Storage扩展存储(存储文件)---公共的
     1、对SD卡的读写权限和操作sd文件夹权限
         android.permission.WRITE_EXTERNAL_STORAGE
        android.permission.READ_EXTERNAL_STORAGE
        android.permission.MOUNT_UNMOUNT_FILESYSTEMS
     2、获得SD卡当前状态
         String state = Environment.getExternalStorageState();
        只有状态  MEDIA_MOUNTED 是正常状态
    3、获取SD卡的路径
         String path = Environment.getExternalStorageDirectory().getAbsolutePath();

三、SQLite Databases数据库存储
    SQL语句
        创建表:create table student(_id integer primary key autoincrement,
                                                name varchar(20), age integer(20), info text);
        新增:insert into student(name,age,info) values("Tom",18,"介绍1");
        删除:delete from student where age>20;
        查找:select name,age from student where name="Shirly";
        修改:update student set age=22 where _id=4;
        删除表:drop table if exists student

     数据库的帮助类    继承SQLiteOpenHelper
       ( 要创建数据库对象,就必须要这个帮助类
          必须实现的方法
              (1) onCreate(SQLiteDatabase db)
                  * 在第一次创建数据库的时候会调用的方法
                 * 在这个方法中一般创建表和初始化表中的数据
                  * @db        创建的数据库对象

              (2) onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
               * 数据版本升级的时候要调用的方法
                 * db        要操作的数据库的对象
                 * oldVersion        数据库的旧版本号
                 * newVersion    数据库的新版本号
              (3)构造方法  继承父类的构造方法
               super(context,  //上下文对象
                        name, //数据库名字
                        factory,  //游标工厂(创建数据)
                        version);    //数据库的版本号,从1开始的
        常用的方法
            getWritableDatabase()    //获取到一个可读可写的数据库对象
            getReadableDatabase()    //获取到的也是一个可读可写的数据库对象。但是在一些特殊情况下,比如磁盘满了,这个数据库对象就变成只读的了。

          操作步骤:
             MyHelper helper = new MyHelper(this, DB_NAME, null, 2); 
            SQLiteDatabase db = helper.getReadableDatabase();
            db.execSQL(sql, new Object[]{});    //增、删、改都用这一步
            查询:
              Cursor cursor = db.rawQuery("select name,age from student", null);
                //cursor.moveToNext():让数据游标依次向下一行移动,如果下一行有数据,返回true
                while(cursor.moveToNext()){
                    //根据列的名字获取列号
                    int nameInde = cursor.getColumnIndex("name");
                    int ageIndex = cursor.getColumnIndex("age");
                    //根据一行里面name字段所在的列号去获取数据(列号从0开始一次增加)
                    String name = cursor.getString(nameInde); 
                    int age = cursor.getInt(ageIndex);
                }
        用API封装好的方法:
       (1) db.insert(TABLE_NAME, null, values);
               *     TABLE_NAME:要插入的表名
                 *     null:没有插入的字段的默认值
                 *     values:要添加的数据
                 *     返回值:插入数据的行号ID。如果返回-1,代表插入数据失败
         (2) db.delete(TABLE_NAME, "name = ?", new String[]{"apple1"});
               *     table:表名
                 *     whereClause:筛选条件where语句(不包括关键字where)
                 *     whereArgs:如果筛选条件有?,那么whereArgs就是筛选条件的具体值
                 *     如果没有where筛选条件,那么后面两个参数都是null
                 *     返回值:删除的行数。如果等于0,说明删除失败
            (3)db.update(TABLE_NAME, values, "_id = ?", new String[]{"15"});
                  *     table:表名
                 *     values:要修改的数据
                 *     whereClause:筛选条件where语句(不包括关键字where)
                 *     whereArgs:如果筛选条件有?,那么whereArgs就是筛选条件的具体值
                 *     如果没有where筛选条件,那么后面两个参数都是null
                 *     返回值:修改数据,受影响的行数
          (4) db.query(TABLE_NAME,    //要查询的表名
                        new String[]{"_id", "name","price"},    //要查询的字段(如果要查询所有字段,则写null)
                        "name = ?",         //筛选条件where语句(不包括关键字where)
                        new String[]{"apple5"},     //如果筛选条件有?,那么selectionArgs就是筛选条件的具体值
                        null, null, null);
                     分页查询
                    //0:查询的第一条数据的下标
                    //10:查询的总共的数据条数
                    Cursor cursor = db.query("food", null, null, null, null, null, null, "0,10");

      数据库适配器    SimpleCursorAdapter
         cursorAdapter = new SimpleCursorAdapter(
                this,        //上下文对象
                android.R.layout.simple_list_item_2,  //每个item要展示的布局文件
                null,             //数据源(cursor)
                new String[]{"name", "price"},     //数据获取的来源    表的字段数组
                new int[]{android.R.id.text1, android.R.id.text2},    //数据的去处        item布局的控件id数组
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);  //标记
        用SimpleCursorAdapter适配器时,必须要查询主键,不然会报错    
        //交换数据源,把cursor放到以前的数据源的位置
        cursorAdapter.swapCursor(cursor);
        //和之前的适配器的区别:SimpleCursorAdapter中的数据源不能进行叠加。

四、Network Connection

    HttpUrlConnection

   HttpUrlConnection是Java.NET包中提供的API,我们知道Android SDK是基于Java的,所以当然优先考虑HttpUrlConnection这种最原始最基本的API,其实大多数开源的联网框架基本上也是基于JDK的HttpUrlConnection进行的封装罢了,掌握HttpUrlConnection需要以下几个步骤: 
   
1、将访问的路径转换成URL。

URL url = new URL(path);

2、通过URL获取连接。

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3、设置请求方式。

conn.setRequestMethod(GET);

4、设置连接超时时间。

conn.setConnectTimeout(5000);

5、设置请求头的信息。

conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));

7、针对不同的响应码,做不同的操作(请求码200,表明请求成功,获取返回内容的输入流)

工具类:

public class StreamTools {
    /**
     * 将输入流转换成字符串
     * 
     * @param is
     *            从网络获取的输入流
     * @return
     */
    public static String streamToString(InputStream is) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            baos.close();
            is.close();
            byte[] byteArray = baos.toByteArray();
            return new String(byteArray);
        } catch (Exception e) {
            Log.e(tag, e.toString());
            return null;
        }
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

HttpUrlConnection发送GET请求

public static String loginByGet(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username= + username + &password= + password;
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod(GET);
            int code = conn.getResponseCode();
            if (code == 200) {
                InputStream is = conn.getInputStream(); // 字节流转换成字符串
                return StreamTools.streamToString(is);
            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 网络访问失败;
        }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

HttpUrlConnection发送POST请求

public static String loginByPost(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod(POST);
            conn.setRequestProperty(Content-Type, application/x-www-form-urlencoded);
            String data = username= + username + &password= + password;
            conn.setRequestProperty(Content-Length, data.length() + );
            // POST方式,其实就是浏览器把数据写给服务器
            conn.setDoOutput(true); // 设置可输出流
            OutputStream os = conn.getOutputStream(); // 获取输出流
            os.write(data.getBytes()); // 将数据写给服务器
            int code = conn.getResponseCode();
            if (code == 200) {
                InputStream is = conn.getInputStream();
                return StreamTools.streamToString(is);
            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 网络访问失败;
        }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

HttpClient

  HttpClient是开源组织Apache提供的Java请求网络框架,其最早是为了方便Java服务器开发而诞生的,是对JDK中的HttpUrlConnection各API进行了封装和简化,提高了性能并且降低了调用API的繁琐,Android因此也引进了这个联网框架,我们再不需要导入任何jar或者类库就可以直接使用,值得注意的是Android官方已经宣布不建议使用HttpClient了。

HttpClient发送GET请求

1、 创建HttpClient对象

2、创建HttpGet对象,指定请求地址(带参数)

3、使用HttpClient的execute(),方法执行HttpGet请求,得到HttpResponse对象

4、调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

5、调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

public static String loginByHttpClientGet(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=
                + username + &password= + password;
        HttpClient client = new DefaultHttpClient(); // 开启网络访问客户端
        HttpGet httpGet = new HttpGet(path); // 包装一个GET请求
        try {
            HttpResponse response = client.execute(httpGet); // 客户端执行请求
            int code = response.getStatusLine().getStatusCode(); // 获取响应码
            if (code == 200) {
                InputStream is = response.getEntity().getContent(); // 获取实体内容
                String result = StreamTools.streamToString(is); // 字节流转字符串
                return result;
            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 网络访问失败;
        }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

HttpClient发送POST请求

1,创建HttpClient对象

2,创建HttpPost对象,指定请求地址

3,创建List,用来装载参数

4,调用HttpPost对象的setEntity()方法,装入一个UrlEncodedFormEntity对象,携带之前封装好的参数

5,使用HttpClient的execute()方法执行HttpPost请求,得到HttpResponse对象

6, 调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

7, 调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

public static String loginByHttpClientPOST(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
        try {
            HttpClient client = new DefaultHttpClient(); // 建立一个客户端
            HttpPost httpPost = new HttpPost(path); // 包装POST请求
            // 设置发送的实体参数
            List parameters = new ArrayList();
            parameters.add(new BasicNameValuePair(username, username));
            parameters.add(new BasicNameValuePair(password, password));
            httpPost.setEntity(new UrlEncodedFormEntity(parameters, UTF-8));
            HttpResponse response = client.execute(httpPost); // 执行POST请求
            int code = response.getStatusLine().getStatusCode();
            if (code == 200) {
                InputStream is = response.getEntity().getContent();
                String result = StreamTools.streamToString(is);
                return result;
            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 访问网络失败;
        }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

参考:

  Android开发请求网络方式详解

Android提供的其他网络访问框架

  HttpClient和HttpUrlConnection的两种网络访问方式编写网络代码,需要自己考虑很多,获取数据或许可以,但是如果要将手机本地数据上传至网络,根据不同的web端接口,需要组织不同的数据内容上传,给手机端造成了很大的工作量。 
   
  目前有几种快捷的网络开发开源框架,给我们提供了非常大的便利。下面是这些项目Github地址,有文档和Api说明。 
   
android-async-http 

http-request

okhttp


五、ContentProvider

一个App需要分享数据库里面的数据给另外一个App---就要用内容提供者
URI:是统一资源标识符,用来唯一的标识一个资源。URI是以一种抽象的,高层次概念定义统一资源标志
          Scheme://authority//path    (协议://认证//路径可有可无)
URL:统一资源定位符,是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联上标准资源的地址。URL是一种具体的URI,

1、访问通话记录
     //读取通话记录的权限
    android.permission.READ_CALL_LOG
     //查询动作的发起者
      ContentResolver resolver = getContentResolver();    
     //获取到通话记录的uri地址
    Uri uri = CallLog.Calls.CONTENT_URI;  //Uri.parse("content://call_log/calls");
    //获取要查询的字段
    String[] colums = new String[]{
                CallLog.Calls._ID,    //主键
                CallLog.Calls.CACHED_NAME,    //通话人的名字
                CallLog.Calls.NUMBER,        //通话的电话号码
                CallLog.Calls.DATE,    //通话的时间
                CallLog.Calls.TYPE        //通话类型        2:拨出    1:打入        3:未接
     };
     //查询
    Cursor cursor = resolver.query(uri, colums, null, null, null);
     //模糊查询
    //Cursor cursor =  resolver.query(uri, null, "name like ?", new String[]{"%name1%"}, null);
    然后绑定SimpleCursorAdapter适配器

2、访问短信记录
    //读取短信记录的权限
     android.permission.READ_SMS
     //查询动作的发起者     ContentResolver resolver = getContentResolver();    
    //获取到通话记录的uri地址
     Uri uri = Uri.parse("content://sms");
    //获取要查询的字段
     String[] colums = new String[]{
                "_id",
                "address",   //电话号码
                "body",
                "type",
                "date"
        };
     //查询
    Cursor cursor = resolver.query(uri, colums, null, null, null);

3、访问联系人
    // 对联系人APP的读写权限
     android.permission.READ_CONTACTS
     android.permission.WRITE_CONTACTS
    涉及到两张表: raw_contacts表和data表
    根据raw_contacts表中的字段 contact_id与data表中的 raw_contact_id对应来找到data表中的data1数据
       //查询动作的发起者
    ContentResolver resolver = getContentResolver();    
    //获取到raw_contacts表的uri地址
     /* content://com.android.contacts/raw_contacts */
    rawUri = ContactsContract.RawContacts.CONTENT_URI;
     //获取到data表的uri地址
    /* content://com.android.contacts/data */
    dataUri = ContactsContract.Data.CONTENT_URI;
    //查询  
    

4、ContentProvider提供方
    1.创建类,继承 ContentProvider抽象类。
      ContentProvider类中六个抽象方法的说明:
        (1) onCreate()   
                 //当内容提供者被创建的时候,这个方法就会被调用(如果provider加载成功,就返回true)
                //一般做初始化工作,比如:创建数据库
                MyHelper helper = new MyHelper(getContext());
                SQLiteDatabase db =helper.getReadableDatabase();
         (2) query()      返回数据给调用者
         (3)insert()     插入新数据到ContentProvider
         (4)update()     更新ContentProvider已经存在的数据
         (5)delete()     从ContentProvider中删除数据
         (6)getType()    返回ContentProvider数据的Mime类型
    2.在AndroidManifest.xml清单中注册ContentProvider
         使用<provider>标签注册ContentProvider,并声明相关的属性
        必要的属性:
             android:name=""    继承ContentProvider类所在的包名.类名
             android:exported="true"        当前的provider里面的数据可以被外部程序访问
              android:authorities=""        用来构造提供给别人的Uri地址中的“认证”信息
                                                    (一般用provider的name属性的值(要把大写改为小写))
5、ContentResolver使用方
    //查询动作的发起者
    ContentResolver resolver = getContentResolver();    
    //获取到uri地址     Uri地址的格式:content://认证 [/路径]
     uri = Uri.parse("content://"+AUTORITY);    
    //其中的AUTORITY等于ContentProvider提供方的清单配置文件中的android:authorities属性的值
    //开始查询
    。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值