博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android的数据管理总结
阅读量:6006 次
发布时间:2019-06-20

本文共 10011 字,大约阅读时间需要 33 分钟。

hot3.png

四大数据存储方式:

一. SharedPreferences

1. 保存:

SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("xml_file_name", Context.MODE_PRIVATE);Editor editor = sharedPreferences.edit();//获取编辑器editor.putString("key", "value");//还可以保存Set
,int,long,float,booleaneditor.commit();//提交修改

默认保存在:/data/data/<package name>/shared_prefs/xml_file_name.xml

2. 读取:

SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("xml_file_name", Context.MODE_PRIVATE);String value = sharedPreferences.getString( "key", "" );

注意:

如果应用A要访问应用B的SharedPreferences,必须先获取应用B的Context,通过B的Context来获取SharedPreferences,才会在应用B所在包下的shared_prefs目录找到XML文件。

二. File

1. 内部资源文件,只读:
InputStream in = getResources().openRawResource(R.raw.test);  //得到资源中的Raw数据流
InputStream in = getResources().getAssets().open(fileName);  //得到资源中的asset数据流

2. 可以读写的文件:

String filePath = getFilesDir().getPath(); //路径:/data/data/<package name>/files
String CachePath = getCacheDir().getPath(); //路径:/data/data/<package name>/cache,换存目录有可能被系统删除
String sdPath = Environment.getExternalStorageDirectory().getPath() // 路径:/mnt/sdCard

 private String read( boolean savedInExternal, String path ){  String result = new String();  FileInputStream in = null;  try{   if( savedInExternal ) {    //SD卡中的文件使用FileInputStream和FileOutputStream进行文件的操作    in = new FileInputStream(path);   } else {    //存放在数据区(/data/data/..)的文件只能使用openFileOutput和openFileInput进行操作    in = openFileInput(path);   }   int len = in.available();   if( len > 0 ){    byte[] buffer = new byte[len];    in.read(buffer);    result = EncodingUtils.getString(buffer, "UTF-8");   }  }catch(Exception e){   e.printStackTrace();  }finally{   if (in != null) {    try {     in.close();    } catch (IOException e) {     // TODO Auto-generated catch block     e.printStackTrace();    }   }  }  return result; }  private void write(boolean savedInExternal, String path, String text){  FileOutputStream out = null;  try{   if(savedInExternal){    out = new FileOutputStream(path);   }else{    out = openFileOutput(path, MODE_PRIVATE);   }   byte[] buffer = text.getBytes();   out.write(buffer);  }catch(Exception e){   e.printStackTrace();  }finally{   if(out!=null){    try {     out.close();    } catch (IOException e) {     e.printStackTrace();    }   }  } }

3.RandomAccessFile同时将FileInputStream和FileOutputStream整合到一起,而且支持访问文件任意字节处读或写数据,常用于断点续传保存文件。

定位用的getFilePointer()
在文件里移动用的seek()
判断文件大小的length()
跳过多少字节数skipBytes()
注意:read()和write(),都是从文件当前位置开始读和写。

//打开文件时,FilePointer指向文件起始位置。RandomAccessFile r = new RandomAccessFile(file,"rwd");   // 将String转byte[],在文件起始位置写入byte[]。String f = "123456789";byte[] buffer = f.getBytes("UTF-8");r.write(buffer);   // 验证:让FilePointer指向文件起始位置。r.seek(0);// 从文件起始位置开始读byte[],然后转String。long len = r.length();byte[] dst = new byte[(int) len];r.read(dst);String f_read = new String(dst,"UTF-8");//结果:123456789   // 让FilePointer指向文件末尾位置,在末尾处接着写入byte[]。r.seek(len);r.write(buffer);   // 验证:让FilePointer指向文件起始位置。从文件起始位置开始读byte[]。r.seek(0);len = r.length();byte[] dst2 = new byte[(int) len];r.read(dst2);f_read = new String(dst2,"UTF-8");//结果:123456789123456789   // 关闭r.close();

三. 数据库(默认路径:/data/data/<package name>/databases/)

在Android平台上,集成了一个嵌入式关系型数据库—SQLite,支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)。
1. SQLiteOpenHelper 是用来管理数据库的,因为是抽象类,所以必须自定义子类来继承它。
SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version)的构造函数中,name表示数据库的名字,默认路径是:/data/data/<package name>/databases/name,可以自定义数据库路径赋值给name,将数据库保存在指定路径下,比如SD卡下。
提供了获取SQLiteDatabase的接口:getReadableDatabase(),getWritableDatabase()。

2. SQLiteDatabase 操作SQLite数据库。

execSQL()接口,主要是执行无需返回数据的操作:
CREATE TABLE IF NOT EXISTS table_name (id INTERGER PRIMARY KEY, content TEXT)
DROP TABLE IF EXISTS table_name
ALTER TABLE table_name ADD COLUMN add_content TEXT
下面的SQL方法也可以用execSQL()执行,也可以使用SQLiteDatabase对应接口。
INSERT INTO table_name (k1,k2) VALUES (v1,v2)
UPDATE table_name SET k1=v1 WHERE 条件
DELETE FROM table_name WHERE 条件

rawQuery()接口,主要是执行返回结果的操作,返回值是结果集游标Cursor:

SELECT * FROM table_name WHERE 条件 GROUP BY 分组 HAVING 分组条件 ORDER BY 排序

public class DatabaseHelper extends SQLiteOpenHelper { private static int DATABASE_VERSION = 1;  public DatabaseHelper(Context context, String dbPath) {  super(context, dbPath, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }}public class DatabaseUtil { private static final String DATABASE_DIR = "database_dir"; private static final String DATABASE_NAME = "database.db";  private Context mContext; private DatabaseHelper mDatabaseHelper; private String mDatabaseDirPath; private String mDatabaseFullPath; private static DatabaseUtil mInstance; //单例模式 public static DatabaseUtil getInstance(Context c) {  if( mInstance == null ) {   mInstance = new DatabaseUtil(c);  }  return mInstance; }  private DatabaseUtil (Context c) {  mContext = c.getApplicationContext();  StringBuffer path = new StringBuffer();  if ( Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED) ) {   File file = Environment.getExternalStorageDirectory();   path.append(file.getPath());  } else {   path.append(mContext.getFilesDir());  }  path.append(File.separator);  path.append(DATABASE_DIR);  mDatabaseDirPath = path.toString();  File dir = new File(mDatabaseDirPath);  if(!dir.exists()){   dir.mkdir();  }  path.append(File.separator);  path.append(DATABASE_NAME);  mDatabaseFullPath = path.toString();  mDatabaseHelper = new DatabaseHelper(mContext, mDatabaseFullPath); }  public void createDatabaseTable(String table){  SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();  db.beginTransaction();//开始事务  try{   StringBuffer str = new StringBuffer();   str.append("CREATE TABLE IF NOT EXISTS ");   str.append(table);   str.append(" (id INTERGER PRIMARY KEY, content TEXT)");   db.execSQL(str.toString());   for(int i = 0; i < 200; ++i){    StringBuffer buf = new StringBuffer();    buf.append("数据:");    buf.append(i+1);    StringBuffer s = new StringBuffer();    s.append("INSERT INTO ");    s.append(table);    s.append(" (id,content) values (?,?)");    db.execSQL(s.toString(), new Object[]{i+1, buf.toString()});   }   db.setTransactionSuccessful();//设置事务的标志为成功  } finally {   db.endTransaction();//由事务的标志决定是提交事务,还是回滚事务   db.close();  } }  public void deleteDatabaseTable(String table) {  SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();  StringBuffer str = new StringBuffer();  str.append("DROP TABLE IF EXISTS ");  str.append(table);  db.execSQL(str.toString());  db.close(); }  public ArrayList
 getDataFromDatabaseTable(String table){  ArrayList
 list = new ArrayList
();  SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();  StringBuffer str = new StringBuffer();  str.append("SELECT * FROM ");  str.append(table);  Cursor c = db.rawQuery(str.toString(),null);  while(c.moveToNext()){   int content_index = c.getColumnIndex("content");   String content = c.getString(content_index);   list.add(content);  }  c.close();  db.close();  return list; }}

四. ContentProvider 向其他应用共享其数据,其他应用通过ContentResolver来访问这些数据。

Android系统提供的常见Content Provider,可以在源码src\android\provider目录中找到。

 

数据传递:

一. Activity, Service, BroadcastReceiver通过Intent对象来实现:

Intent的功能包括启动四大组件以及相关信息+传递数据。
其中传递数据Intent提供了putExtra和对应的getExtra方法,所以无需再创建一个bundle对象。
对应自定义数据结构,可以封装成Serializable和Parcelable来实现序列化。
但是,数据类型有限,比如遇到不可序列化的数据Bitmap,InputStream,或者LinkList链表等数据类型就不太好。
1. Serializable使用IO读写存储在外存上,在序列化时会产生大量的临时变量,从而引起频繁的GC,适用于保存对象的字节序列到本地文件或数据库中,以及网络传输。
自定义数据结构只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可。
使用ObjectOutputStream.writeObject()可以将自定义数据写入文件流或网络流。
使用ObjectInputStream.readObject()可以从文件流或网络流中读取自定义数据。
2. Parcelable是直接在内存中读写,是通过IBinder通信的消息的载体,只适用进程间传递对象。
需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,务必保持写入和读取的类型及顺序一致,否则会发生异常。

二. 利用Application定义的全局变量:

A通过getApplication()对全局变量进行值的修改,B可以访问Application的值。修改全局变量的代码段需要用synchronized包裹来实现同步,防止多线程同时修改。

三. 通过单例模式实现:

可以保证Application中的这个类有且只有一个实例。在A中设置参数,在B中直接访问了。

public class Singleton  {      //单例模式实例      private static Singleton instance = null;            //synchronized 用于线程安全,防止多线程同时创建实例      public synchronized static Singleton getInstance(){          if(instance == null){              instance = new Singleton();          }             return instance;      }               private HashMap
 mMap;      public Singleton()      {          mMap = new HashMap
();      }            public void put(String key,Object value){          mMap.put(key,value);      }            public Object get(String key)     {          return mMap.get(key);      }}

四. 通过Handler实现线程间的消息传递:

Handler类的主要作用有两个:
    1.在新启动的线程中发送消息。
    2.在主线程中获取、处理消息。

五. 基于外部存储的传输,使用SharedPreferences,File,SQLite,针对第三方应用需要ContentProvider+ContentResolver。

六. 基于IPC通信机制:

1. 定义AIDL接口文件实现进程间通信:

为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现,使用接口定义语言(Interface Definition Language,IDL)来公开服务的接口。

建立AIDL服务的步骤:

(1)在工程的Java包目录中建立一个扩展名为aidl的文件。每个文件只能定义一个接口,而且只能是接口的声明和方法的声明。

(2)如果aidl文件的内容是正确的,刷新工程,ADT会在gen包下自动生成一个Java接口文件(*.java)

(3)建立一个服务类(Service的子类),定义了一个内嵌类来实现.aidl文件定义的Java接口。

(4)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。如果服务端service定义了android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。

客户端获取接口:

(1)将服务端自动生成的IMyService.java文件连同包目录一起复制到客户端工程的src目录中(R文件除外).

(2)客户端通过ServiceConnection获取从Service返回的IBinder,bindService以后可调用服务器的接口

2. 通过Messager实现进程间通信:

使用场景:当仅有2个应用要互相通讯时

(1)service 内部需要有一个 Handler 的实现,它被用来处理从每一个 client 发送过的来请求
(2)通过这个 Handler ,来生成一个 Messenger
(3) 在 service 的onBind() 方法中,需要向 client 返回由该 Messenger 生成的一个 IBinder 实例
(4) client 使用从 service 返回的 IBinder 实例来初始化一个 Messenger, 然后使用该 Messenger 与 service 进行通信
(5) service 通过它自身内部的 Handler 实现(Handler 人 handleMessage() 方法中)来处理从 client 发送过来的请求

转载于:https://my.oschina.net/u/1984976/blog/375354

你可能感兴趣的文章
opencv边缘检测的入门剖析(第七天)
查看>>
第六天a
查看>>
struts2.1.6 + hibernate3.3 + spring3.0 遇到的问题
查看>>
Maven学习(3) - Maven和Eclipse集成和构建多模块Maven项目
查看>>
成员变量与局部变量
查看>>
linux 强制终止进程命令
查看>>
第一个Sprint冲刺第九天
查看>>
六一儿童节
查看>>
重学Android——Glide4.x源码分析(2)
查看>>
TMCache源码分析(一)---TMMemoryCache内存缓存
查看>>
教你在不使用框架的情况下也能写出现代化 PHP 代码
查看>>
语法专题---数据类型的转换
查看>>
bootstrapt model 的多罩层,禁用罩层
查看>>
大咖分享 | ProjectMan是如何炼成的
查看>>
微信测试账号和本地开发调试
查看>>
Spring Cloud云服务架构 - HongHu代码结构构建
查看>>
从零开始写一个 redux(第三讲)
查看>>
vue-cli3 多页面多入口,分别打包
查看>>
Codeforces Round #269 (Div. 2) D - MUH and Cube Walls kmp
查看>>
RabbitMQ错误检查
查看>>