Android开发-数据存储与IO

一.数据存储分类

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条件匹配的全部记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值