Android 数据存储汇总

作者: uniapp | 来源:发表于2018-07-23 14:57 被阅读28次

    Android 应用中常常会将一些数据保存到手机中,比如我们常见的偏好设置。将数据保存在本机,能够适配用户喜好,提供更好的用户体验。

    Android 保存数据,有 4 种常见的方式:

    1. 保存在内部的私有文件夹;
    2. sharedPreference;
    3. sd 卡的公共部分;
    4. 存储到数据库中;

    Android 的文件目录,分为以下几类:
    1 system/app 系统自带的应用程序,无法删除。
    2 data/app 用户程序安装的目录,有删除权限。安装时把apk文件复制到此目录。
    3 data/data 存放应用程序的数据。Androd 会为每一个新安装的 App 生成一个目录,称为沙盒,用于保存应用程序运行时生成的数据。
    4 data/dalvik-cache 将apk中的dex文件安装到 dalvik-cache 目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一)。

    xml 数据的保存和读取

    Android 中可以用 XmlSerializer 类生成 xml 文件格式的数据。

    @Override
        public void onClick(View v) {
            String student_name = et_name.getText().toString().trim();
            String student_number = et_number.getText().toString().trim();
    
            int rg_id = rg_sex.getCheckedRadioButtonId();
            switch (rg_id){
                case R.id.rg_man:
                    sex = "男";
                    break;
                case R.id.rg_female:
                    sex = "女";
                    break;
                default:
                    sex = "保密";
                        break;
            }
    
            if (TextUtils.isEmpty(student_name) || TextUtils.isEmpty(student_number) || TextUtils.isEmpty(sex)){
                Toast.makeText(this, "信息不能为空", Toast.LENGTH_SHORT).show();
                return;
            }
    
            XmlSerializer serializer = Xml.newSerializer();
            File file = new File(getFilesDir(), student_name+".xml");
            try {
                OutputStream os = new FileOutputStream(file);
                serializer.setOutput(os, "utf-8");
    
                serializer.startDocument("utf-8", true);
                serializer.startTag(null,"student");
    
                serializer.startTag(null, "name");
                serializer.text(student_name);
                serializer.endTag(null, "name");
    
                serializer.startTag(null, "sex");
                serializer.text(sex);
                serializer.endTag(null, "sex");
    
                serializer.startTag(null, "number");
                serializer.text(student_number);
                serializer.endTag(null, "number");
    
                serializer.endTag(null,"student");
    
                serializer.endDocument();
                os.close();
                Toast.makeText(this, "信息保存到文件成功", Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    其生成的文件内容为:

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?><student><name>uniapp</name><sex>男</sex><number>110</number></student>
    

    通过XmlPullParser 类解析 xml 格式文件:

     public void onClick(View v){
            XmlPullParser pullParser = Xml.newPullParser();
            InputStream in = null;
            try {
                File file = new File(getFilesDir(), "uniapp.xml");
                pullParser.setInput(new FileInputStream(file), "utf-8");
                int eventType = pullParser.getEventType();
    
                Student st = null;
                while (eventType!=XmlPullParser.END_DOCUMENT){
    
                    if (eventType== XmlPullParser.START_TAG){
    
                        if ("student".equals(pullParser.getName())){
                            st = new Student();
                        }
                        else if ("name".equals(pullParser.getName())){
                            String name = pullParser.nextText();
                            st.setName(name);
                        }else if ("sex".equals(pullParser.getName())){
                            String sex = pullParser.nextText();
                            st.setSex(sex);
                        }
                        else if ("number".equals(pullParser.getName())){
                            String number = pullParser.nextText();
                            st.setNumber(number);
                        }
                    }
    
                    eventType = pullParser.next();
                }
    
                if (st != null){
                    Toast.makeText(this, st.toString(), Toast.LENGTH_LONG).show();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    Android 中 SharedPreference 的存取
    private SharedPreferences sp ;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_setting);
    
            LinearLayout layout_setting = findViewById(R.id.layout_setting);
            final CheckBox cb = findViewById(R.id.checkBox);
            SeekBar sb = findViewById(R.id.seekBar);
            sp =  getSharedPreferences("setting", 0);
    
            Boolean isChecked = sp.getBoolean("isCheck", false);
            cb.setChecked(isChecked);
            sb.setProgress(sp.getInt("progress", 0));
            layout_setting.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    cb.setChecked(!cb.isChecked());
                    SharedPreferences.Editor et = sp.edit();
                    et.putBoolean("isCheck", cb.isChecked());
                    et.commit();
                }
            });
    
            sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    
                }
    
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
    
                }
    
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                    sp =  getSharedPreferences("setting", 0);
                    SharedPreferences.Editor et = sp.edit();
                    et.putInt("progress", seekBar.getProgress());
                    et.commit();
                }
            });
        }
    
    Android 数据库的存取

    Androi 中封装了 sqlitLite 数据库,继承至 SQLiteOpenHelper 即可找到使用接口:

    public class StudentDbOpenHelper extends SQLiteOpenHelper {
        public StudentDbOpenHelper(Context context) {
            super(context, "student.db", null, 10);
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("create table students (_id integer primary key autoincrement, _name vachar(30), " +
                    "_sex varchar(10))");
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    //        db.execSQL("alter table students add _sex varchar(10)");
        }
    }
    

    将数据库的增删改查封装封装为操作类 StudentDao :

    public class StudentDao {
    
    
        StudentDbOpenHelper helper;
    
        public StudentDao(Context context) {
            helper = new StudentDbOpenHelper(context);
    
        }
    
        public void add(Student st){
    
            SQLiteDatabase db = helper.getWritableDatabase();
            db.execSQL("insert into students values(null,?,?)",
                    new Object[]{st.getName(), st.getSex()});
    
    //        ContentValues contentValues = new ContentValues();
    //        contentValues.put("name", st.getName());
    //        contentValues.put("sex", st.getSex());
    //        db.insertOrThrow("students", null, contentValues)
        }
        public void delete(String id){
            SQLiteDatabase db = helper.getWritableDatabase();
            db.execSQL("delete from students where _id = ?", new Object[]{id});
        }
        public void update(Student st){
            SQLiteDatabase db = helper.getWritableDatabase();
            db.execSQL("update students set _name=?,_sex=? where _id=?", new Object[]{
                st.getName(),st.getSex(), st.getId()
            });
        }
        public Student find(String id){
            SQLiteDatabase db = helper.getReadableDatabase();
            Cursor cursor = db.rawQuery("select * from students where _id=?", new String[]{id});
    
            Boolean res = cursor.moveToNext();
            Student st = null;
            if (res){
                 int id1 = cursor.getInt(0);
                String name = cursor.getString(1);
                String sex = cursor.getString(2);
                st = new Student(String.valueOf(id1), name, sex);
            }
            return st;
        }
    
        //查询所有学生信息
        public List<Student> getAll(){
            SQLiteDatabase db = helper.getReadableDatabase();
            Cursor cursor = db.rawQuery("select * from students" ,null);
            List<Student> list = new ArrayList<Student>();
            while (cursor.moveToNext()){
                Student st = new Student(String.valueOf(cursor.getInt(0)), cursor.getString(1),
                        cursor.getString(2));
                list.add(st);
            }
            return list;
        }
    }
    

    覆盖 Student 类的 toString 方法:

    public class Student {
        private String id;
        private String name;
        private String sex;
    
        public Student(String id, String name, String sex) {
            this.id = id;
            this.name = name;
            this.sex = sex;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        @Override
        public String toString() {
            return this.getId() + " name: " + this.getName() + " sex: " + this.getSex();
        }
    }
    

    最后在 Activity 的 listView 中进行展示:

    public class SqliteActivity extends AppCompatActivity {
        ListView listView;
        StudentDao sd;
        List<Student> list_students;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_sqlite);
            listView = findViewById(R.id.listView);
            sd = new StudentDao(this);
        }
    
        private MyAdapter myAdapter;
        public void onClick(View v){
            list_students = sd.getAll();
            if (myAdapter == null){
                myAdapter = new MyAdapter();
                listView.setAdapter(myAdapter);
            }else {
                myAdapter.notifyDataSetChanged();
            }
    
        }
    
        class MyAdapter extends BaseAdapter {
    
            @Override
            public int getCount() {
                return list_students.size();
            }
    
            @Override
            public Object getItem(int position) {
                return null;
            }
    
            @Override
            public long getItemId(int position) {
                return 0;
            }
    
    
            //position: 位置; convertView: 用于优化; parent: item 所在的父控件;
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view;
                if (convertView!=null){
                    view = convertView;
                }else {
                    view = View.inflate(SqliteActivity.this, R.layout.item_student, null);
                }
                ImageView iv = view.findViewById(R.id.item_iv);
                TextView tv = view.findViewById(R.id.item_tv);
                final Student student = list_students.get(position);
                ImageView iv_delete = view.findViewById(R.id.iv_delete);
                iv_delete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AlertDialog.Builder builder = new AlertDialog.Builder(SqliteActivity.this);
                        builder.setTitle("删除...");
                        builder.setMessage("删除吗?");
                        builder.setPositiveButton("删除", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String id =  student.getId();
                                sd.delete(id);
                                Toast.makeText(SqliteActivity.this, "删除成功", Toast.LENGTH_SHORT).show();
                                SqliteActivity.this.onClick(null);
                            }
                        });
                        builder.setNegativeButton("取消", null);
                        builder.create();
                        builder.show();
                    }
                });
                String sex = student.getSex();
                if ("男".equals(sex)){
                    iv.setImageResource(R.drawable.nan1);
                }else {
                    iv.setImageResource(R.drawable.nv);
                }
                tv.setText(position +  student.getName());
                return view;
            }
        }
    }
    
    Android 在存储数据工程中会出现的两种问题
    1. oom : 内存溢出,占用内存过高,被系统杀死;
    2. memery leak: 内存泄漏,对象占用内存忘记释放;
    Android 5 种进度条实现方式
    //确认取消
        public void show1(View view){
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("新信息");
            builder.setMessage("约饭吗?");
            builder.setPositiveButton("约", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(ListActivity.this, "可以", Toast.LENGTH_SHORT).show();
                }
            });
    
            builder.setNegativeButton("算了吧", null);
            builder.show();
    
        }
        //单选
        public void show2(View view){
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("单选");
    
            String[] items = {"小丽", "小红", "小芳"};
            builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(ListActivity.this, "item is " + which, Toast.LENGTH_SHORT).show();
                }
            });
            builder.show();
        }
        //多选
        public void show3(View view){
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("单选");
            String[] items = {"小丽", "小红", "小芳"};
            final boolean[] checkdItems = {true, false, true};
            builder.setMultiChoiceItems(items, checkdItems, new DialogInterface.OnMultiChoiceClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which, boolean isChecked) {
    //                checkdItems[which] = isChecked;
                    Toast.makeText(ListActivity.this, "item is " + which + " " + isChecked, Toast.LENGTH_SHORT).show();
                }
            });
            builder.show();
        }
        //进度条
        public void show4(View view){
            final ProgressDialog dialog = new ProgressDialog(this);
            dialog.setMessage("正在加载中...");
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.setMax(100);
    
    
            Thread t = new Thread(new Runnable() {
    
                @Override
    
                public void run() {
    
                    try {
                        for (int i = 0; i <= 100; i=i+10){
                            Thread.sleep(1000);
                            dialog.setProgress(i);
                        }
                        //子线程沉睡
                        //让他显示10秒后,取消ProgressDialog
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    dialog.dismiss();
                }
            });
            dialog.show();
            t.start();
        }
        //进度转盘
        public void show5(View view){
    
            final ProgressDialog dialog = ProgressDialog.show(this, "",
    
                    "下载数据,请稍等 …", true, true);
    
            Thread t = new Thread(new Runnable() {
    
                @Override
    
                public void run() {
    
                    try {
                        //子线程沉睡
                        Thread.sleep(10000);//让他显示10秒后,取消ProgressDialog
    
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    dialog.dismiss();
                }
            });
            t.start();
        }
    
    喜欢和关注都是对我的鼓励和支持~

    相关文章

      网友评论

        本文标题:Android 数据存储汇总

        本文链接:https://www.haomeiwen.com/subject/eqxrmftx.html