一.数据存储分类
1.SharedPreferences
- 通过键值对形式保存简单的、私有的数据
2.文件存储:内部存储和外部存储
- 把私有数据保存在设备的内部存储介质中
- 把公用数据保存在共享的外部存储介质中
3.SQLite 数据库
- 把结构化的数据保存在一个私有的数据库中
4.网络存储
- 把数据保存在网络上开发者自己的服务器中
5.ContentProvider
- 获取和保存其他应用程序暴露的数据
二.SharedPreferences
1.SharedPreferences概述
- 常用来存储应用的配置信息、用户设置参数等数据量不大的数据
- key-value对方式存储基本数据类型:整型、布尔型、长整型和字符串
- 存放在ROM中所属应用程序的目录中,以XML文件格式存储
- /data/data/应用程序包名/shared_prefs/
2.SharedPreferences读数据
- SharedPreferences本身是一个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name,int mode)获取SharedPreferences实例
- Mode参数常用值
- Context.MODE_PRIVATE:SP中的数据只能被本应用程序读写
- Context.MODE_WORLD_READABLE:SP中的数据能被其他应用程序读,但不能写
- Context.MODE_WORLD_WRITEABLE:SP中的数据能被其他应用程序读、写
3.SharedPreferences写数据
- SharedPreferences接口本身没有提供写入数据的能力,通过SharedPreferences的内部接口实现。
- SharedPreferences调用edit()方法获取它对应的Editor对象,Editor提供了方法向sharedPreferences写入数据
- SharedPreferences.Editor clear():清空SharedPreferences中的数据
- SharedPreferences.Editor putXxx(String key, xxx Value)向SharedPreferences存入指定key对应的数据
- Boolean commit():当Editor编辑完成后,调用该方法提交修改
4.SharedPreferences例子-记住用户名和密码
实现第一次登陆保存密码
第二次进入软件用户名和密码就自动出现
public class MainActivity extends AppCompatActivity {
private CheckBox checkBox;
private EditText edituser,editpass;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化控件
SharedPreferences preferences=getSharedPreferences("user", Context.MODE_PRIVATE);
if(preferences!=null){
String user=preferences.getString("user","");//后面第二个是没有获取到时赋值给user为空
String pass=preferences.getString("pass","");
edituser.setText(user);
editpass.setText(pass);
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(checkBox.isChecked()){
SharedPreferences sharedPreferences=getSharedPreferences("user", Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sharedPreferences.edit();
String user=edituser.getText().toString();
String pass=editpass.getText().toString();
editor.putString("user",user);
editor.putString("pass",pass);
editor.commit();
}
Intent intent=new Intent();
intent.setClass(MainActivity.this,Main2Activity.class);//前往登陆成功页面
startActivity(intent);
}
});
}
private void initView() {
checkBox=(CheckBox) findViewById(R.id.checkBox);
edituser=(EditText) findViewById(R.id.editText);
editpass=(EditText) findViewById(R.id.editText2);
button=(Button) findViewById(R.id.button);
}
}
5.SharedPreferences例子-实现自动提示软件打开次数
- 我感觉思路有两个
- 一个是存储一个int的数据,该数据保存从第一次开始为1,保存下一次打开的次数,下一次执行读取,提示
- 同样是存储一个int的数据,但该数据从第一次初始化为0,+1操作,存储本次打开的次数,Toast提示本次打开的次数
public class MainActivity extends AppCompatActivity {
private CheckBox checkBox;
private EditText edituser,editpass;
private Button button;
private SharedPreferences preferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
preferences=getSharedPreferences("user", Context.MODE_PRIVATE);
if(preferences!=null){
String user=preferences.getString("user","");
String pass=preferences.getString("pass","");
int count=preferences.getInt("count",1);
Toast.makeText(MainActivity.this,"你已经打开本软件"+count+"次了",Toast.LENGTH_SHORT).show();
count++;
SharedPreferences.Editor editor=preferences.edit();
editor.putInt("count",count);
editor.commit();
edituser.setText(user);
editpass.setText(pass);
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
preferences=getSharedPreferences("user", Context.MODE_PRIVATE);
if(checkBox.isChecked()){
SharedPreferences.Editor editor=preferences.edit();
String user=edituser.getText().toString();
String pass=editpass.getText().toString();
editor.putString("user",user);
editor.putString("pass",pass);
editor.commit();
}
Intent intent=new Intent();
intent.setClass(MainActivity.this,Main2Activity.class);
startActivity(intent);
}
});
}
private void initView() {
checkBox=(CheckBox) findViewById(R.id.checkBox);
edituser=(EditText) findViewById(R.id.editText);
editpass=(EditText) findViewById(R.id.editText2);
button=(Button) findViewById(R.id.button);
}
}
6.SharedPreferences注意
- getSharedPreferences是Context类中的方法,可以指定file name 以及 mode
- 一般用于自定义的一些偏好设置
- getPreferences是Activity类中的方法,只需指定mode
- 默认采用所在的类名作为xml文件的名称
- 每个应用有一个默认的偏好文件preferences.xml,使用getDefaultSharedPreferences获取
- PreferenceManager.getDefaultSharedPreferences(this)
- 读取其他的SharedPreferences
- 当应用程序创建的SharedPreferences指定了可被其他应用访问的权限时,该SharedPreferences中的数据可以被其他程序读取
- 在应用程序中访问其他程序创建的SharedPreferences的步骤
- 创建其他程序对应的Context
- 调用其他应用的Context的getSharedPreferences(Stringname,int mode)获得相应的SharedPreferences对象
- 如果需要写入数据,调用SharedPreferences的edit()方法获得相应的Editor即可
三.文件存储
- File文件读写
- SDCard存储
- adb常用命令
1.File存储
- 通过字节流和字符流两种方式读写Android设备的ROM和SDCard的文件
- 默认为内部存储,数据存在应用程序目录中,是应用程序私有的
- dada/data/应用程序包名/files/
- 应用程序卸载则所有文件被删除
- SDCard:外部存储,将数据存储在SDCard中,为所有程序共享
- 需要SDCard读写权限
- 模拟器路径:mnt/sdcard/
- 可以长期保存,亦可连接到PC上进行操作
2.常用方法
- Context提供了访问应用程序数据文件夹的方法
- getDir(String name,int mode):在应用程序下获取戒创建name对应的子目录
- File getFileDir():获取该应用程序的数据文件夹的绝对路径
- String[] fileList():返回该应用程序的数据文件夹下的全部文件
- deleteFile(String):删除该应用程序的数据文件夹下的指定文件
3.例子一
public class MainActivity extends AppCompatActivity {
private Button button1,button2;
private EditText editText1,editText2;
private final String FILE_NAME="sutang1.nsu";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
button1=(Button) findViewById(R.id.button);
button2=(Button) findViewById(R.id.button1);
editText1=(EditText) findViewById(R.id.editText);
editText2=(EditText) findViewById(R.id.editText1);
button1.setOnClickListener(new ClickEvent());
button2.setOnClickListener(new ClickEvent());
}
public class ClickEvent implements View.OnClickListener{
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button://写入操作
write(editText1.getText().toString());
Toast.makeText(MainActivity.this,"写入成功!",Toast.LENGTH_SHORT).show();
editText1.setText("");
editText2.setText("");
break;
case R.id.button1://读取操作
editText2.setText(read());
break;
}
}
}
public void write(String str){
try {
FileOutputStream fos=openFileOutput(FILE_NAME,MODE_APPEND);
PrintStream ps=new PrintStream(fos);
//输出文件内容
ps.println(str);
fos.close(); //关闭输出流
}catch (FileNotFoundException e){
throw new RuntimeException(e);
}catch (IOException e){
throw new RuntimeException(e);
}
}
public CharSequence read(){
try {
FileInputStream fis = openFileInput(FILE_NAME);
byte [] bys=new byte[1024];
int len=0;
StringBuilder sb=new StringBuilder();
while((len=fis.read(bys))>0){
sb.append(new String(bys,0,len));
}
fis.close();
return sb.toString();
}catch (FileNotFoundException e){
throw new RuntimeException(e);
}catch (IOException e){
throw new RuntimeException(e);
}
}
}
4.SDCard存储
- 若移动设备连接到PC上(将其视为USB存储设备),此时移动设备上的应用不能使用外部存储
- SD卡槽接触不良或SD卡被拆下或其他不可用状态
- 在使用SDCard存储前要检查可用性
- Environment.getExternalStorageState()
- Environment.MEDIA_MOUNTED:可读写外部存储介质
- Environment.MEDIA_MOUNTED_READ_ONLY:只能读不能写
- Environment.MEDIA_REMOVED:被移除
- 操纵SD卡中的文件
- 为了读写SD卡上的数据需要配置如下权限
- 在sdcard上创建及删除文件的权限
- Android.permission.MOUNT_UNMOUNT_FILESYSTEMS
- 往sdcard写入数据的权限
- Android.permission.WRITE_EXTERNAL_STORAGE
5.SDCard存储例子一
- 要先在AndroidManifest.xml配置权限
<!-- 在sdcard上创建及删除文件的权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往sdcard写入数据的权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
public class MainActivity extends AppCompatActivity {
private Button button1, button2;
private EditText editText1, editText2;
private final String SD_FILE = "/mySDfile.nsu";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
button1 = (Button) findViewById(R.id.button);
button2 = (Button) findViewById(R.id.button1);
editText1 = (EditText) findViewById(R.id.editText);
editText2 = (EditText) findViewById(R.id.editText1);
button1.setOnClickListener(new ClickEvent());
button2.setOnClickListener(new ClickEvent());
}
public class ClickEvent implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button://写入操作
write_SD(editText1.getText().toString());
Toast.makeText(MainActivity.this, "写入成功!", Toast.LENGTH_SHORT).show();
editText1.setText("");
break;
case R.id.button1://读取操作
editText2.setText(read_SD());
break;
}
}
}
public void write_SD(String str) {
try {
//手机插入了sd卡,且应用程序具有访问SD的权限
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//获取sd卡目录
File sdCardDir = Environment.getExternalStorageDirectory();
//getCanonicalPath()获取规范路径名
File tarFile = new File(sdCardDir.getCanonicalPath() + SD_FILE);
//以指定文件创建RandomAccessFile对象
RandomAccessFile raf = new RandomAccessFile(tarFile, "rw");
//将文件记录指针移动到最后
raf.seek(tarFile.length());
//输出文件内容
raf.write(str.getBytes());
//关闭RandomAccessFile
raf.close();
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public CharSequence read_SD() {
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//获取SD卡对应的存储目录
File sdCardDir = Environment.getExternalStorageDirectory();
//获取指定文件对应的输入流
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(sdCardDir.getCanonicalPath() + SD_FILE)));
StringBuilder sb = new StringBuilder("");
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();//关闭输入流
return sb.toString();
}
return null;
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
6.常用adb命令
(1).创建SDCard
- cmd进入tools目录输入mksdcard 100M D:\mysdcard.img
(2).激活sdcard
- 如果在开发环境(Eclipse)中,可以在Run Configuration对话框中设置启动参数
- -sdcard F:\mysdcard.img
(3).sdcard中加入内容
- adb push E:\Xunlei\give.mp3 /sdcard/give.mp3
(4).查看sdcard
- adb shell
(5).常用adb命令
- #开始shell命令
- adb shell
- #进入到sdcard卡目录
- cd sdcard
- #将列出所有文件夹
- ls
- #删除文件戒文件夹
- rm -r (文件/文件夹名称)
四.SQLite数据库
1.SQLite数据库概述
- 轻量级的数据库
- 嵌入式的数据库引擎,专门用于资源有限的设备上
- 不像Oracle、MySQL那样需要安装和启动
- SQLite数据库只是一个文件
注意:如果实际项目中有大量数据需要读写,或者并发访问,要放在服务器端的DATABASE,手机毕竟还是手机
2.SQLiteDatabase简介
Android提供了SQLiteDatabase代表数据库。一旦指定了数据库的SQLiteDatabase对象,就可以通过SQLiteDatabase对象来管理、操作数据库了
SQLiteDatabase提供3种静态方法打开数据库
static SQLiteDatabase openDatabase(String
path,SQLiteDatabase.CursorFactory factory,int flags):打开path文件所代表的SQLite数据库。
static SQLiteDatabase opernOrCreateDatabase(File
file,SQLiteDatabase.Cursor factory):打开或创建file文件所代表的SQLite数据库。
static SQLiteDatabase openOrCreateDatabase(String
path,SQLiteDatabase.CursorFactory factory):打开或创建path文件所代表的SQLite数据库。
3.SQLiteDatabase操作数据库
- 获得SQLiteDatabase对象后,就可以调用SQLiteDatabase方法操作数据库
- 常用方法
- execSQL(String sql,Object[] bindArgs)执行带占位符的SQL语句
- execSQL(String sql)执行SQL语句
- rawQuery(String sql,String[] selectionArgs)执行带占位符的查询
- 常用方法
4.SQLiteDatabase常用方法
- insert(String table,String nullColumnHack, ContentValuesvalues):添加一条记录,表名、列名、参数集合
- delete(String table,String whereClause,String[] whereArgs):删除表中特定数据,表名、满足的条件、为条件传入的参数
- update(String table,ContentValues values,StringwhereClause,String[] whereArgs):修改特定数据,表名、想更新的数据,满足的条件、为条件传入的参数
- query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having, String orderBy):查询数据,表名、列名、查询条件、查询参数、分组、聚合函数、排序
5.常用sql语句示例
(1).创建表
String sql = "create table dict(_id integer primary key
autoincrement,word text,detail text)";
db.execSQL(sql);
(2),插入数据
db.execSQL("insert into user_info values(null,?,?)",new String[]{"小明","女"});
(3).删除数据
db.execSQL(“delete from user_info where _id = ?”,new String[]{cursor.getInt(positions)+“”})
(4).查询数据
String sql = "select * from dict where word like ? or detail like ?";
Cursor cursor = db.rawQuery(sql,new String[]{"%"+key+"%","%"+key+"%"});
6.SQLiteDatabase查询
- 查询方法返回一个Cursor对象,通过移动指针遍历查询结果
Cursor常用方法
- move(int offset)将指针向上戒向下移动指定的行数
- boolean moveToFirst()移动到第一行
- boolean moveToLast()移动到最后一行,成功则返回true
- boolean moveToNext()移动到下一行
- boolean moveToPosition(int position)移动到指定的行
- boolean moveToPrevious()移动到上一行
解析Cursor
- 利用SimpleCursorAdapter解析Cursor
- SimpleCursorAdapter(Context context,int layout,Cursor c,String[] from,int[] to,int flags)
- flags推荐取值
- CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER
- SimpleCursorAdapter adapter = new SimpleCursorAdapter(context,R.layout.line,cursor,
new String[]{“news_title”,”news_content”},new int[]{R.id.my_title,R.id.my_content})
注意:数据库表的主键列的列明必须为_id,否则会出现错误java.lang.IllegalArgumentException:column”_id” does not exist
7.SQLiteDatabase例子一
public class MainActivity extends AppCompatActivity {
;private EditText editText1,editText2;
private Button button1,button2;
private ListView listView;
private SQLiteDatabase db;
private Cursor cursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
db=SQLiteDatabase.openOrCreateDatabase(this.getFilesDir()+"/user.db",null);//创建或者打开数据库,使用绝对路径
}
private void initView() {
editText1=(EditText) findViewById(R.id.editText);
editText2=(EditText)findViewById(R.id.editText2);
button1=(Button) findViewById(R.id.button);
button2=(Button) findViewById(R.id.button2);
listView=(ListView) findViewById(R.id.listview);
button1.setOnClickListener(new ClickEvent());
button2.setOnClickListener(new ClickEvent());
}
public class ClickEvent implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
String user_id=editText1.getText().toString().trim();
String user_name=editText2.getText().toString().trim();
try{
if(user_id.equals("")&&user_name.equals("")){
Toast.makeText(MainActivity.this, "数据不能为空", Toast.LENGTH_SHORT).show();
}
else{
insertData(db,user_id,user_name);
Toast.makeText(MainActivity.this, "数据插入成功!", Toast.LENGTH_SHORT).show();
editText1.setText("");
editText2.setText("");
}
}catch (SQLiteException e){
//创建数据表
db.execSQL("create table user_info(_id integer primary key autoincrement,"
+"user_id varchar(50),"
+"user_name varchar(255))");
//执行insertData语句,插入数据
insertData(db,user_id,user_name);
Toast.makeText(MainActivity.this, "数据插入成功!", Toast.LENGTH_SHORT).show();
editText1.setText("");
editText2.setText("");
}
break;
case R.id.button2:
if(isTableExit("user_info")){
cursor=db.rawQuery("select * from user_info",null);
inflateList(cursor);
}else{
Toast.makeText(MainActivity.this,"数据表不存在,请插入数据",Toast.LENGTH_SHORT).show();
}
break;
}
}
private void inflateList(Cursor cursor) {
SimpleCursorAdapter adapter = new SimpleCursorAdapter(MainActivity.this,R.layout.sql_list_item,//ListView每一个单位的布局文件
cursor,new String[] {"user_id","user_name"},
new int[]{R.id.my_title,R.id.my_content},
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listView.setAdapter(adapter);
}
private boolean isTableExit(String tableName) {
boolean result = false;
if (tableName == null) {
return false;
}
try {
String sql = "select count(*) as c from sqlite_master where " +
"type ='table' and name ='"+tableName.trim()+"' ";
Cursor cursor = db.rawQuery(sql, null);
if (cursor.moveToNext()) {
int count = cursor.getInt(0);
if (count>0) {
result = true;
}
}
} catch (Exception e) {
}
return result;
}
public void insertData(SQLiteDatabase db, String userId, String userName) {
//执行插入语句
db.execSQL("insert into user_info values(null,?,?)"
,new String[]{userId,userName});
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//退出程序时关闭数据库
if (db != null && db.isOpen()){
db.close();
}
}
}
8.使用SQLiteDatabase进行数据库操作的步骤
- 获取SQLiteDatabase对象,它代表了不数据库的连接
- 调用SQLiteDatabase的方法来执行SQL语句
- execSQL(……)、rawQuery(……)
- 操作SQLiteDatabase的查询结果,比如用SimpleCursorAdapter封装Cursor
- 关闭SQLiteDatabase,回收资源
五.SQLiteOpenHelper
- 上面中,我们先尝试插入数据,如果抛出异常,在catch块中来新建数据表
- 在查询的时候,我们自定义了一个方法isTableExist(String tableName)来判断表是否存在,一点儿也不优雅!!!
注意:在实际项目中很少使用SQLiteDatabase的方法来打开数据库,通常会继承SQLiteOpenHelper开发子类。通过子类的getReadableDatabase()、 getWritableDatabase() 方法打开数据
1.SQLiteOpenHelper类概述
SQLiteOpenHelper是Android提供的一个管理数据库的工具类,可以用于管理数据库的创建和版本更新
创建SQLiteOpenHelper的子类,重写以下方法
- onCreate(SQLiteDatabase db)当第一次创建数据库时回调该方法
- onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)当数据库版本更新时回调该方法
一旦得到SQLiteOpenHelper对象后,程序无需使用SQLiteDatabase的静态方法创建SQLiteDatabase实例,可以使用getWriteableDatabase()和getReadableDatabase()方法来获取一个用于操作数据库的SQLiteDatabase实例
打开数据库
- getReadableDatabase():以读的方式打开数据库对应的SQLiteDatabase对象
- getWriteableDatabase():以写的方式打开数据库对应的SQLiteDatabase对象
- 关闭数据库
- close():关闭所有打开的SQLiteDatabase
2.SQLiteOpenHelper类例子-生词本
我们先来写SQLiteOpenHelper的子类,重写它的两个方法
public class DatabaseHelper extends SQLiteOpenHelper{
public DatabaseHelper(Context context, String name, int version) {
super(context, name,null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql="create table if not exists dict(_id integer primary key "+
"autoincrement,word text,detail text)";
db.execSQL(sql);//执行这个sql语句
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
因为有ListView,所以要设置Adapter,继承BaseAdapter
public class WordAdpater extends BaseAdapter {
private Context context;
private List<Map<String,String>> listItems;
private LayoutInflater inflater;
public WordAdpater(Context context,List<Map<String,String>> listItems){
this.context=context;
this.listItems=listItems;
this.inflater=LayoutInflater.from(context);
}
@Override
public int getCount() {
return listItems.size();
}
@Override
public Object getItem(int position) {
return listItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=null;
final int positions=position;
if(convertView==null){
holder=new ViewHolder();
convertView=inflater.inflate(R.layout.items,null);//ListView每一个单位的风格
holder.eid=(TextView)convertView.findViewById(R.id.eid);
holder.English=(TextView) convertView.findViewById(R.id.English);
holder.Chinese=(TextView) convertView.findViewById(R.id.chinese);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
holder.eid.setText((String) listItems.get(position).get("id"));
holder.English.setText((String) listItems.get(position).get("word"));
holder.Chinese.setText((String) listItems.get(position).get("detail"));
return convertView;
}
public class ViewHolder{
public TextView eid;
public TextView English;
public TextView Chinese;
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private DatabaseHelper dbHelper;
private EditText et_word;
private EditText et_detail;
private EditText et_key;
private Button btn_add;
private Button btn_search;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper=new DatabaseHelper(this,"OurDict.db",1);//后面两个是数据库名称以及版本
init();
}
private void init() {
et_word=(EditText) findViewById(R.id.editText1);
et_detail=(EditText)findViewById(R.id.editText2);
et_key= (EditText) findViewById(R.id.editText3);
btn_add=(Button) findViewById(R.id.button1);
btn_search=(Button) findViewById(R.id.button2);
btn_add.setOnClickListener(this);
btn_search.setOnClickListener(this);
}
public void onClick(View v){
switch (v.getId()){
case R.id.button1:
String word=et_word.getText().toString();
String detail=et_detail.getText().toString();
if(word==null||detail==null||word.trim().length()==0||detail.trim().length()==0){
Toast.makeText(this,"不要为空",Toast.LENGTH_SHORT).show();
break;
}
String sql1="insert into dict values (null,?,?)";
SQLiteDatabase db=dbHelper.getReadableDatabase();
db.execSQL(sql1,new String[]{word,detail});
Toast.makeText(this,"生词添加成功",Toast.LENGTH_SHORT).show();
et_word.setText("");
et_detail.setText("");
break;
case R.id.button2:
String key=et_key.getText().toString();
String sql2="select * from dict where word like ? or detail like ?";
Cursor cursor=dbHelper.getReadableDatabase()
.rawQuery(sql2,new String[]{"%"+key+"%","%"+key+"%"});
List<Map<String,String>> result=new ArrayList<Map<String,String>>();
while(cursor.moveToNext()){
Map<String,String> map=new HashMap<String,String>();
map.put("id",cursor.getInt(0)+"");
map.put("word",cursor.getString(1));
map.put("detail",cursor.getString(2));
result.add(map);
}
Bundle data=new Bundle();
data.putSerializable("data", (Serializable) result);
Intent intent=new Intent();
intent.setClass(this,ResultActivity.class);
intent.putExtras(data);
startActivity(intent);
break;
}
}
}
public class ResultActivity extends AppCompatActivity {
private ListView listview;
private DatabaseHelper dbHepler;
private List<Map<String,String>> result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
Intent intent=getIntent();
Bundle bundle=intent.getExtras();
dbHepler=new DatabaseHelper(this, "OurDict.db", 1);
result= (List<Map<String, String>>) bundle.getSerializable("data");
listview=(ListView) findViewById(R.id.listView1);
final SimpleAdapter adapter=new SimpleAdapter(ResultActivity.this,result,
R.layout.items,new String[]{"word","detail"},
new int[]{R.id.English,R.id.chinese});
listview.setAdapter(adapter);
listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
final int positions=position;
new AlertDialog.Builder(ResultActivity.this)
.setItems(R.array.button_array,new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
String context=getResources().getStringArray(R.array.button_array)[which];
if(context.equals("修改")){
View v=getLayoutInflater().inflate(R.layout.view,null);
final EditText word=(EditText) v.findViewById(R.id.editText12);
final EditText detail=(EditText) v.findViewById(R.id.editText13);
final String u_word=result.get(positions).get("word");
final String u_detail=result.get(positions).get("detail");
word.setText(u_word);
detail.setText(u_detail);
new AlertDialog.Builder(ResultActivity.this)
.setTitle("是否要删改单词???")
.setView(v)
.setPositiveButton("确定要修改",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
String sql="update dict set word = ?,detail=? where _id=?";
String up_word=word.getText().toString();
String up_detail=detail.getText().toString();
dbHepler.getReadableDatabase().execSQL(sql,new String[]{up_word,up_detail,result.get(positions).get("id")});
if(!up_word.equals(u_word)){
result.get(positions).put("word",up_word);
}
if(!up_detail.equals(u_detail)){
result.get(positions).put("detail",up_detail);
}
adapter.notifyDataSetChanged();
}
})
.setNegativeButton("取消",null)
.create()
.show();
}else if(context.equals("删除")){
new AlertDialog.Builder(ResultActivity.this)
.setTitle("是否要删除单词???")
.setPositiveButton("确定要删除",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
String sql="delete from dict where _id = ?";
dbHepler.getReadableDatabase().execSQL(sql, new String[]{result.get(positions).get("id")});
result.remove(positions);
adapter.notifyDataSetChanged();
}
})
.setNegativeButton("取消",null)
.create()
.show();
}
}
})
.create()
.show();
return true;
}
});
}
}
六.ContentProvider
1.ContentProvider简介
- ContentProvider是不同应用程序之间数据交换标准API,以URI的形式对外提供数据。
- 当应用程序需要将自己的数据暴露给其他程序时,该应用程序可以通过提供ContentProvider来实现,其他应用程序可通过ContentResolver来操作此ContentProvider
2.ContentProvider的使用
(1).开发步骤
- 定义自己的ContentProvider类,该类需要继承Android提供的ContentProvider基类
- 向Android系统注册该ContentProvider,注册ContentProvider时需要为它绑定Uri
在AndroidManifest.xml文件的<application ...>元素下添加如下子元素即可
<!-- 下面配置中name属性指定ContentProvider类
authorities就相当于为该ContentProvider指定的域名-->
<provider android:name=“.DictProvider”
android:authorities=“com.example.providers.dictprovider”
android:exported=“true”/>
3.编写自己的ContentProvider
- 继承ContentProvider,并实现如下方法,完成CRUD操作
public boolean onCreate():该方法在创建ContentProvider后被调用
public uri insert(Uri uri,ContentValue values):根据该uri插入values对应的数据。
public int delete(Uri uri,String selection,String[] selectionArgs):根据uri删除select条件匹配的全部记录。
public int update(Uri uri,ContentValue values,String selection, String[] selectionArgs):根据uri修改selection匹配的所有记录
public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs, String sortOrder):根据Uri查询select条件匹配的全部记录。