Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 558|回复: 0

开发交流:Android 文件的共享

[复制链接]

该用户从未签到

发表于 2011-10-24 09:38:30 | 显示全部楼层 |阅读模式
   一、使用SQLite实现对数据的操作:

  第一步:建立一个要操作的表对应的javabean
  第二步:创建一个类,继承SQLiteOpenHelper(完成数据库和表的创建,以及软件升级时,对数据库、表结构进行更新)
  第三步:创建一个类,实现对数据的CRUD操作(将SQLiteOpenHelper的实例传入其中,从而可以对数据库进行操作)
  第四步:编写测试类,对第三步编写的CRUD操作进行测试,包括分页显示数据

  第五步:配置清单文件以及布局文件

java代码: package eoe.android.dbhelper;



import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteDatabase.CursorFactory;

import android.database.sqlite.SQLiteOpenHelper;



public class DBHelper extends SQLiteOpenHelper{

private static String db_name = "contacts.db";

private static int version = 1;



/**

* 在DBHelper初始化

*/



public DBHelper(Context context) {

//CursorFactory指定在执行查询时获得一个游标实例的工厂类。 设置为null,则使用系统默认的工厂类。

super(context, db_name, null, version);

}



/**

* 真正使用到DBHelper类的时候回调用该方法的时候,注意不是DBhelper初始话的时候就会调用该方法

* 还有要注意的一点就是:DBhelper初始的时候实际上也不会帮我们去创建数据库,在使用到真正使用到

* DBHelper的时候系统会查看db_name数据库是否已经存在,如果 不存在则创建,该数据库文件保存的位置

* 为Android系统根目录下/data/data/标识应用的所在包的包名 /databases/我们自己定义的数据库名

*/



public void onCreate(SQLiteDatabase db) {

db.execSQL("CREATE TABLE IF NOT EXISTS contacts("+"_id Integer primary key autoincrement," +"name varchar(20)," +"phone varchar(30)"+")");

}



/**

* 如果软件的版本发生变化,则会调用该方法,在该方法中可以更改数据库及表的结构

* 例如,上面设置的版本号version为1,程序运行一遍之后将version值改为2,当再次

* 运行该程序的时候就会调用该方法,有点困惑的地方就是版本发生变化的时候,执行完

* 该方法后还会去执行以下onCreate方法,不知道为什么 ?

*/



@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

db.execSQL("DROP TABLE IF EXISTS contacts");

this.onCreate(db);

}



}
复制代码二、数据库操作类(CRUD)

java代码: package eoe.android.sqlite.service;



import java.util.ArrayList;

import java.util.List;

import android.content.Context;

import android.database.Cursor;

import com.heima.android.dbhelper.DBHelper;

import com.heima.android.sqlite.bean.Contact;



public class ContactService {

private DBHelper dbHelper;

//定义一个构造器,用于初始化一个DBHelper,

public ContactService(Context context){

this.dbHelper = new DBHelper(context);

}



/*

* 新增数据,sql语句使用占位符,与PrepareStatement类似,bindArgs为要填充到占位符中的数据

* 使用dbHelper的getReadableDatabase()方法可以得到一个SQLiteDatabase实例,进而可以操作数据库*/



public void saveContact(Contact contact){

String sql = "insert into contacts(name,phone)values(?,?)";

Object[] bindArgs = {contact.getName(),contact.getPhone()};

dbHelper.getWritableDatabase().execSQL(sql, bindArgs);

}



/*

* 根据id删除数据

*/



public void deleteContact(Integer id){

String sql = "delete from contacts where _id=?";

Object[] bindArgs = {id};

dbHelper.getReadableDatabase().execSQL(sql, bindArgs);

}



/*

* 根据数据

*/



public void updateContact(Contact contact){

String sql = "update contacts set name=?,phone=? where _id=?";

Object[] bindArgs = {contact.getName(),contact.getPhone(),contact.get_id()};

dbHelper.getWritableDatabase().execSQL(sql, bindArgs);

}



/* 根据id查询某个联系人信息

* 最近项目中用到很多查询数据的地方,都用到了Cursor,但是对Cursor的moveToFirst和moveToNext用法却有些疑惑,

* 总感觉可以先用moveToFirsrt来判断查询结果是否为空,然后再用moveToNext的while循环来逐条读取数据,我也不知道

* 最初我这种想法从何而来,似乎是这样想的,当用ContentProvider查询得到一个cursor的时候,cursor应该是处于指向

* 第一条记录的位置,因此调不调用moveToFirst都是一样的。可是后来写着写着就觉得矛盾了,如果真的是得到的cursor

* 就指向第一条,那么不调用moveToFirst,直接使用while(moveToNext())的循环岂不是把第一条给跳过去了?

* 越想越糊涂,还是直接看代码,又写了个例子debug了一下,原来查询得到的cursor是指向第一条记录之前的,因此查询得到

* cursor后第一次调用moveToFirst或moveToNext都可以将cursor移动到第一条记录上。源码中这些moveXXX其实都是通过moveToPosition

* 来实现的,而记录position的是一个整型变量mPos。当moveXXXX返回false的时候,mPos会被置为-1,也就是回到了初始状态,指向第一条记录之前。

* 这里记录一下自己犯下的这个错误。

*/



public Contact findContactById(Integer id){

String sql = "select _id,name,phone from contacts where _id=?";

String[] selectionArgs = {id+""};

//由于这里要求的是String类型的数据,所以加个空字符串进行处理

Cursor cursor = dbHelper.getReadableDatabase().rawQuery(sql, selectionArgs);

if(cursor.moveToFirst()){

return new Contact(cursor.getInt(0), cursor.getString(1), cursor.getString(2));

}

return null;

}



/*

* 获取查询出的记录总数

*

*/



public long getCount(){

String sql = "select count(*) from contacts";

Cursor cursor = dbHelper.getReadableDatabase().rawQuery(sql, null);

cursor.moveToNext();

return cursor.getLong(0);

  

}
复制代码java代码: /*

* 获取分页数据供SimpleAdapter使用,数据中封装在List中,这种方法不可行,下面有解释

*/





/* public List< Contact> getScollDataList(long startIndex,long pageSize){

String sql = "select * from contacts limit ?,?";

String[] selectionArgs = {String.valueOf(startIndex),String.valueOf(pageSize)};

Cursor cursor = dbHelper.getReadableDatabase().rawQuery(sql, selectionArgs);

List< Contact> contactList = new ArrayList();

//首先判断cursor中是否有数据,

if(cursor.moveToFirst()){//要特别要注意的是: 这样在进行分页时,始终会忽略掉第一条记录

while(cursor.moveToNext()){

Contact contact = new Contact(cursor.getInt(0),cursor.getString(1),cursor.getString(2));

contactList.add(contact);

}

return contactList;

}

return null;

}*/



/*

* 获取分页数据供SimpleAdapter使用,数据中封装在List中

*/



public List< Contact> getScollDataList(int startIndex,int pageSize){

String sql = "select * from contacts limit ?,?";

String[] selectionArgs = {String.valueOf(startIndex),String.valueOf(pageSize)};

Cursor cursor = dbHelper.getReadableDatabase().rawQuery(sql, selectionArgs);

List< Contact> contactList = new ArrayList();

while(cursor.moveToNext()){

Contact contact = new Contact(cursor.getInt(0),cursor.getString(1),cursor.getString(2));

contactList.add(contact);



}

cursor.close();

return contactList;

}





/*

* 获取分页数据供SimpleCursorAdapter使用,数据封装在Cursor中

*/



public Cursor getScollDataCursor(long startIndex,long pageSize){

String sql = "select * from contacts limit ?,?";

String[] selectionArgs = {String.valueOf(startIndex),String.valueOf(pageSize)};

Cursor cursor = dbHelper.getReadableDatabase().rawQuery(sql, selectionArgs);

return cursor;

}

}
复制代码二、使用SharedPreferences共享数据
  一般用来保存软件参数,等小数据
  优点:它是一个轻量级的存储类,操作方便,
  确定,不宜保存大数据,只能够保存boolean、string、float、long、int类型的原子数据,一般只供本应用使用
  (1)使用方法(保存数据):
  1、通过上下文对象获得一个SharedPreferences对象。
  2、利用得到SharedPreferences对象获得一个Edit对象,使用Edit对象实现对简单数据的保存,注意要记得Edit的commit方法

  (2)使用方法(获取数据):
  1、通过上下文对象获得一个SharedPreferences对象。
  2、使用SharedPreferences对象的get方法获取数据。
  需要注意的地方:使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data//shared_prefs目录下:

java代码: package eoe.android.service;



import java.util.HashMap;

import android.content.Context;

import android.content.SharedPreferences;

import android.content.SharedPreferences.Editor;



public class SharedPreferencesService {

private Context context;

public SharedPreferencesService() {

}



public SharedPreferencesService(Context applicationContext) {

this.context = applicationContext;

}



/**

* 使用SharedPreferences保存软件设置参数

* @param name 需要保存的参数名称

* @param age 需要保存的参数名称

*/

public void save(String name, String age) {

SharedPreferences preferences = this.context.getSharedPreferences("heima",context.MODE_PRIVATE);

Editor edit = preferences.edit();

edit.putString("name", name);

edit.putInt("age", Integer.parseInt(age));

edit.commit();//执行commit方法后,edit中设置的内容才真正写入文件中

}

/**

* 从SharedPreferences中获取数据用于在界面回显

* @return 保存的数据

*/



public HashMap getData(){

HashMap map = new HashMap();

SharedPreferences preferences = this.context.getSharedPreferences("heima", context.MODE_WORLD_READABLE);

String name = preferences.getString("name", "");

int age = preferences.getInt("age", 0);

map.put("name", name);

map.put("age", age+"");

return map;

}}
复制代码三、使用内容提供者ContentProvider存取数据

  首先明白ContentProvider是什么:在实际的应用中,每个应用都可以创建自己的数据,但是这个数据对其他应用来说是不可见的,当某个应用需要将自己的数据共享给其他应用使用时,
  我们就需要使用到内容提供者ContentProvider,使用ContentProvider去访问某个应用程序的数据,让我们不必关心某个应用程序是的数据存储方式是使用数据库还是使用文件方式,还是通过
  网络获取数据,这些都不重要,重要的是其他应用程序可以通过ContentProvider这个统一的接口操作某个应用程序的数据。如果一个程序想让其他程序操作自己的数据就必须定义自己的ContentProvider
  然后再清单文件中进行注册,其他应用程序就可以根据ContentProvider定义的Uri对某一应用程序的数据进行操作。
  android中的电话本等数据就是通过ContentProvider实现数据共享的,系统中有很多已经存在的共享Uri。我们可以使用ContentResolver通过Uri来操作不同表的数据;如Contacts.People.CONTENT_URI
  什么是URI?
  将其分为A,B,C,D 4个部分:
  A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"
  B:URI 的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称 ;"content://hx.android.text.myprovider"

    C:路径path,注意这里的路径不一定是表名,这里的路径只是一个匹配符号,例如content://com.heima.providers.userprovider/user,这里的user可以不是一个表名,只是标识,当符合这个标识进入Provider的相应方法时候,
  就要依据Contentprovider里面的方法里使用的表名进行操作。

  D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;
  "content://hx.android.text.myprovider/tablename/#" #表示数据id
  
       如何定义和使用自己的ContentProvider

  第一步:定义自己的ContentProvider,必须继承ContentProvider,根据业务的需要实现相应的方法,要注意的是,我们自己定义的ContentProvider要提供对数据操作的入口(本例中的内容提供者是对数据库进行操作
  当然,也可以对文件类型的数据进行操作),所以这里要传入一个SQLiteOpenHelper对象的引用
  第二步:要记得在项目清单文件中配置我们自定义的ContentProvider,
  第三步:在其他应用中使用ContentResolver对ContentProvider进行访问(实际上ContentResolver对象签名方法在内部最终是根据传入的Uri拿到对应的ContentProvider对象,实现对数据的操作)

  两个有用的方法:ContentUris

  自定义ContentProvider中用到的类有:
  (1)ContentProvider(2)SQLiteOpenHelper、 SQLiteDatabase(3)UriMatCher(方法:addURI、match)、ContentUris(方法: parseId(uri)、withAppendedId(uri))
  使用ContentProvider的应用中需要用到类
  ContentResolver、ContentValues

      1、自定义ContentProvider:

java代码: package eoe.android.dbhelper;



import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteDatabase.CursorFactory;

import android.database.sqlite.SQLiteOpenHelper;



public class DBHelper extends SQLiteOpenHelper{

private static String db_name = "contacts.db";

private static int version = 1;

/**

* 在DBHelper初始化

*/



public DBHelper(Context context) {
复制代码java代码: //CursorFactory指定在执行查询时获得一个游标实例的工厂类。 设置为null,则使用系统默认的工厂类。

super(context, db_name, null, version);

}



/**

* 真正使用到DBHelper类的时候回调用该方法的时候,注意不是DBhelper初始话的时候就会调用该方法

* 还有要注意的一点就是:DBhelper初始的时候实际上也不会帮我们去创建数据库,在使用到真正使用到

* DBHelper的时候系统会查看db_name数据库是否已经存在,如果 不存在则创建,该数据库文件保存的位置

* 为Android系统根目录下/data/data/标识应用的所在包的包名 /databases/我们自己定义的数据库名

*/



public void onCreate(SQLiteDatabase db) {



db.execSQL("CREATE TABLE IF NOT EXISTS contacts("+"_id Integer primary key autoincrement," +"name varchar(20)," +"phone varchar(30)"+")");

}



/**

* 如果软件的版本发生变化,则会调用该方法,在该方法中可以更改数据库及表的结构

* 例如,上面设置的版本号version为1,程序运行一遍之后将version值改为2,当再次

* 运行该程序的时候就会调用该方法,有点困惑的地方就是版本发生变化的时候,执行完

* 该方法后还会去执行以下onCreate方法,不知道为什么 ?

*/



@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

db.execSQL("DROP TABLE IF EXISTS contacts");

this.onCreate(db);

}



}
复制代码2、在清单文件中进行配置  < !-- 配置自定义的ContentProvider -->
  < provider android:name=".UserContentProvider" android:authorities="com.heima.providers.userprovider"/>

  3、用于测试使用ContentProvider共享数据的另一个应用

java代码: package eoe.demo;



import android.content.ContentResolver;

import android.content.ContentValues;

import android.net.Uri;

import android.test.AndroidTestCase;

import android.util.Log;



/**

* 测试使用ContentProvider操作另外一个应用中的数据

* @author Administrator

* time 下午09:16:24

*/



public class UserContentProviderTest extends AndroidTestCase {

private static String TAG = "UserContentProviderTest";



/**

*测试添加数据,

*/



public void testInsert(){

Log.i(TAG, "executing testInsert()1.........");

Uri uri = Uri.parse("content://com.heima.providers.userprovider/user");

ContentResolver contentResolver = this.getContext().getContentResolver();

ContentValues contentValues = new ContentValues();

contentValues.put("account", "lganggang131");

contentValues.put("password", "123456");

contentValues.put("nickname", "sky");



//晕的死,竟然把Scheme和要操作的表忘记写了,报了个Unknown URL异常,狂晕

// contentResolver.insert(Uri.parse("com.heima.providers.userprovider"), contentValues);contentResolver.insert(Uri.parse("com.heima.providers.userprovider"), contentValues);

Log.i(TAG, "executing testInsert()2.........");

contentResolver.insert(uri, contentValues);

Log.i(TAG, "executing testInsert()3.........");

}



}
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-10 23:00 , Processed in 0.314179 second(s), 38 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表