20189200余超 2018-2019-2 移动平台应用开发实践第十周作业
20189200余超 2018-2019-2 移动平台应用开发实践第十周作业
偏好
在Android应用中,我们常需要记录用户设置的一些偏好参数,,此时我们就需要用SharedPreferences和Editor将这些信息保存下来,在下次登录时读取。
SharedPreferences保存的数据主要类似于配置信息格式的数据,因此它保存数据的形式为key-value对,下面我们来看下实例代码。
首先是界面布局,比较简单,就是一个普通的登陆界面.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" >
<EditText android:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/account"/>
<EditText android:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/password"android:layout_below="@id/account"/>
<Button android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_below="@id/password"android:text="保存参数"android:id="@+id/save"android:onClick="save"/>
</RelativeLayout>
这是自定义的Preferences 类,用来实现数据的保存 ,可在Android的内置存储空间产生一文件。
import android.R.integer;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.widget.EditText;public class Preferences {private Context context;public Preferences(Context context){this.context=context;}public void save(String name, Integer valueOf) {//保存文件名字为"shared",保存形式为Context.MODE_PRIVATE即该数据只能被本应用读取SharedPreferences preferences=context.getSharedPreferences("shared",Context.MODE_PRIVATE);Editor editor=preferences.edit();editor.putString("name", name);editor.putInt("age", valueOf);editor.commit();//提交数据}
}
下面是Mainactivity的代码。在activity的oncreate阶段我们加载本地的数据。
import java.util.HashMap;
import java.util.Map;import android.R.integer;
import android.os.Bundle;
import android.app.Activity;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;public class MainActivity extends Activity {private EditText account,passworad;Preferences prefer;//自定义的类SharedPreferences preference; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);account=(EditText)findViewById(R.id.account);passworad=(EditText)findViewById(R.id.password);//获取本地的数据preference=getSharedPreferences("shared", MODE_PRIVATE);Map<String, String> map=new HashMap<String, String>();map.put("name",preference.getString("name",""));map.put("age", String.valueOf(preference.getInt("age", 0))); account.setText(map.get("name"));passworad.setText(map.get("age"));}//保存文件的方法public void save(View v) {String name=account.getText().toString();String age=passworad.getText().toString();prefer=new Preferences(this);prefer.save(name,Integer.valueOf(age));Toast.makeText(getApplicationContext(), "保存完成", Toast.LENGTH_SHORT).show();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}
我们看一下效果.
点击保存参数,出现保存完成则说明我们已经保存成功了,在下次登录的时候可以看到这些参数还在。因为记录文件是在内置空间中的,所以我们在SD卡中找不到该文件,
如果有root权限的手机可以下载个RE文件管理,我们可以再/data/data/的路径找到很多应用程序的内置文件夹,我们可以在这些文件夹中看到一个shared_prefs文件夹,
里面就有我们刚刚设置而产生的xml文件。
操作空间
我们先来考虑这样一个问题:
打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的时候又是清除的哪里的数据?读完本文相信你会有答案。
在android开发中我们常常听到这样几个概念,内存,内部存储,外部存储,很多人常常将这三个东西搞混,那么我们今天就先来详细说说这三个东西是怎么回事?
内存,我们在英文中称作memory,内部存储,我们称为InternalStorage,外部存储我们称为ExternalStorage,这在英文中本不会产生歧义,但是当我们翻译为中文之后,前两个都简称为内存,于是,混了。
那么究竟什么是内部存储什么是外部存储呢?
首先我们打开DDMS,有一个File Explorer,如下:
彻底理解android中的内部存储与外部存储0
这里有三个文件夹需要我们重视,一个是data,一个是mnt,一个是storage,我们下面就详细说说这三个文件夹。
1.内部存储
data文件夹就是我们常说的内部存储,当我们打开data文件夹之后(没有root的手机不能打开该文件夹),里边有两个文件夹值得我们关注,如下:
一个文件夹是app文件夹,还有一个文件夹就是data文件夹,app文件夹里存放着我们所有安装的app的apk文件,其实,当我们调试一个app的时候,可以看到控制台输出的内容,有一项是uploading .....就是上传我们的apk到这个文件夹,上传成功之后才开始安装。另一个重要的文件夹就是data文件夹了,这个文件夹里边都是一些包名,打开这些包名之后我们会看到这样的一些文件:
1.data/data/包名/shared_prefs
2.data/data/包名/databases
3.data/data/包名/files
4.data/data/包名/cache
如果打开过data文件,应该都知道这些文件夹是干什么用的,我们在使用sharedPreferenced的时候,将数据持久化存储于本地,其实就是存在这个文件中的xml文件里,我们App里边的数据库文件就存储于databases文件夹中,还有我们的普通数据存储在files中,缓存文件存储在cache文件夹中,存储在这里的文件我们都称之为内部存储。
2.外部存储
外部存储才是我们平时操作最多的,外部存储一般就是我们上面看到的storage文件夹,当然也有可能是mnt文件夹,这个不同厂家有可能不一样。
一般来说,在storage文件夹中有一个sdcard文件夹,这个文件夹中的文件又分为两类,一类是公有目录,还有一类是私有目录,其中的公有目录有九大类,比如DCIM、DOWNLOAD等这种系统为我们创建的文件夹,私有目录就是Android这个文件夹,这个文件夹打开之后里边有一个data文件夹,打开这个data文件夹,里边有许多包名组成的文件夹。
说到这里,我想大家应该已经可以分清楚什么是内部存储什么是外部存储了吧?好,分清楚之后我们就要看看怎么来操作内部存储和外部存储了。
3.操作存储空间
首先,经过上面的分析,大家已经明白了,什么是内部存储,什么是外部存储,以及这两种存储方式分别存储在什么位置,一般来说,我们不会自己去操作内部存储空间,没有root权限的话,我们也没法操作内部存储空间,事实上内部存储主要是由系统来维护的。不过在代码中我们是可以访问到这个文件夹的。由于内部存储空间有限,在开发中我们一般都是操作外部存储空间,Google官方建议我们App的数据应该存储在外部存储的私有目录中该App的包名下,这样当用户卸载掉App之后,相关的数据会一并删除,如果你直接在/storage/sdcard目录下创建了一个应用的文件夹,那么当你删除应用的时候,这个文件夹就不会被删除。
经过以上的介绍,我们可以总结出下面一个表格:
一目了然,什么是内部存储,什么是外部存储。
如果按照路径的特征,我们又可以将文件存储的路径分为两大类,一类是路径中含有包名的,一类是路径中不含有包名的,含有包名的路径,因为和某个App有关,所以对这些文件夹的访问都是调用Context里边的方法,而不含有包名的路径,和某一个App无关,我们可以通过Environment中的方法来访问。如下图:
操作数据库
public class MainActivity extends AppCompatActivity {private MyDatabaseHelper dbHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 3); // 执行这句并不会创建数据库文件Button btnCreateDatabase = (Button) findViewById(R.id.button);btnCreateDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dbHelper.getWritableDatabase(); // 执行这句才会创建数据库文件}});}
}
public class MyDatabaseHelper extends SQLiteOpenHelper {public static final String CREATE_BOOK = "create table book (" +"id integer primary key autoincrement, " +"author text, " +"price real," +"pages integer, " +"name text)";private Context mContext;public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);mContext = context;}/*** 数据库已经创建过了, 则不会执行到,如果不存在数据库则会执行* @param db*/@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK); // 执行这句才会创建表Toast.makeText(mContext, "create succeeded", Toast.LENGTH_SHORT).show();}/*** 创建数据库时不会执行,增大版本号升级时才会执行到* @param db* @param oldVersion* @param newVersion*/@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 在这里面可以把旧的表 drop掉 从新创建新表,// 但如果数据比较重要更好的做法还是把旧表的数据迁移到新表上,比如升级qq聊天记录被删掉肯定招骂Toast.makeText(mContext, "onUpgrade oldVersion:" + oldVersion + " newVersion:" + newVersion, Toast.LENGTH_SHORT).show();}
}
验证数据库文件是否存在的方法看最后部分
剩下的工作就是对数据库表的增删改查了
首先通过下面的代码获得一个引用以便操作数据库
1 SQLiteDatabase db = dbHelper.getWritableDatabase();
对于增删改都可以用 db.execSQL(String sql); 来执行sql语句。 例如增加一条记录
1 db.execSQL("insert into book(name , author, pages, price) values("Android数据库操作指南", "panda fang", 200, 35.5)");
遇到字符串要转义 有没有觉得很蛋疼, 用下面的方法就好多了
1 db.execSQL("insert into book(name , author, pages, price) values(?, ? ,? ,? )", new String[]{"Android数据库操作指南", "panda fang", "200", "35.5"});
sql 中用 ? 占位 后面传入真正的参数, 由于在创建表的时候已经约定pages 和 price字段的数据类型为integer和real, 虽然代码中写的是字符串并不影响,存入数据库会自动处理的。数组嘛,必须与其他的元素类型一致。 这第二个方式是 execSQL(String sql)的重载方法 api是 public void execSQL(String sql, Object[] bindArgs) throws SQLException
对于查询则要使用 rawQuery(String sql, String[] selectionArgs) , 因为 execSQL返回void ,而查询需要访问查询结果。方法如下:
Cursor cursor = db.rawQuery("select * from book", null);
while (cursor.moveToNext())
{String name = cursor.getString(cursor.getColumnIndex("name"));String author = cursor.getString(cursor.getColumnIndex("author"));Log.i(TAG, "name:" + name + " author:" + author);
}
cursor.close();
如何检查数据库文件是否存在,以及检查表中的数据呢。
前提是使用模拟器或者root过的真机。从 android studio 菜单中 Tools -> Android -> Android Device Monitor -> File Explorer 找到 data/data/程序包名/databases 目录
查看是否存在数据库文件。如果存在可以导出到电脑上, 用 以下工具查看数据库中的表
获取图片
import java.io.FileNotFoundException;import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;import com.maikefengchao.daixu.R;public class WriteArticle_CompeterelayActivity extends BaseActivity {private ImageView im_upload_img;@Overridepublic void initView(Bundle savedInstanceState){setContentView(R.layout.view_write_competerelay);im_upload_img = (ImageView)findViewById(R.id.write_competerelay_cover_iv);}@Overrideprotected void setListener() {im_upload_img.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent();/* 开启Pictures画面Type设定为image */intent.setType("image/*");/* 使用Intent.ACTION_GET_CONTENT这个Action */intent.setAction(Intent.ACTION_GET_CONTENT);/* 取得相片后返回本画面 */startActivityForResult(intent, 1);}});}@Overrideprotected void processLogic(Bundle saveInstanceState) {}//获取本地图片@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (resultCode == RESULT_OK) {Uri uri = data.getData();String img_url = uri.getPath();//这是本机的图片路径ContentResolver cr = this.getContentResolver();try {Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));ImageView imageView = (ImageView) findViewById(R.id.write_competerelay_cover_iv);/* 将Bitmap设定到ImageView */imageView.setImageBitmap(bitmap);} catch (FileNotFoundException e) {Log.e("Exception", e.getMessage(),e);}}super.onActivityResult(requestCode, resultCode, data);}
}
statistics.sh
转载于:https://www.cnblogs.com/yuchao123/p/10808757.html
20189200余超 2018-2019-2 移动平台应用开发实践第十周作业相关推荐
- 20189200余超 2018-2019-2 移动平台应用开发实践第七周作业
20189200余超 2018-2019-2 移动平台应用开发实践第七周作业 布局 在这一节中首先学习了java的页面布局,在此基础之上来进行了编程. 图片如下: 代码如下: *** 使用代码进行登录 ...
- 20189200余超 2018-2019-2 移动平台应用开发实践第六周作业
20189200余超 2018-2019-2 移动平台应用开发实践第六周作业 Android简介.活动.UI组件 1.Android系统架构 这是Android系统架构图,够一目了然了吧,Androi ...
- 20189200余超 2018-2019-2 移动平台应用开发实践第八周作业
20189200余超 2018-2019-2 移动平台应用开发实践第八周作业 ListView 1.自定义BaseAdapter,然后绑定ListView的最简单例子 先看看我们要实现的效果图: 一个 ...
- 20189200余超 2018-2019-2 移动平台应用开发实践第十一周作业
20189200余超 2018-2019-2 移动平台应用开发实践第十一周作业 制作视频 本节是Android多媒体基本API调用的一节,带来的是MediaRecord的简单使用, 用法非常简单,我们 ...
- 20189200余超 2018-2019-2 移动平台应用开发实践第三周作业
2018-2019-2 移动平台应用开发实践第三周作业 核心类 基本类型的封装类 封装类: java语言认为一切皆对象.8个基本数据类型野应该具备对应的对象.通过封装类可以把8个基本类型的值封装对象进 ...
- 20189200余超 2018-2019-2 移动平台应用开发实践第十二周作业
20189200余超 2018-2019-2 移动平台应用开发实践第十二周作业 服务 Service的声明 Service是Android中的四大组件,使用它一定要在AndroidManifest.x ...
- 20189200余超 2018-2019-2 移动平台应用开发实践第五作业
20189200余超 2018-2019-2 移动平台应用开发实践第五作业 输入/输出 输入输出可以说是计算机的基本功能.作为一种语言体系,java中主要按照流(stream)的模式来实现.其中数据的 ...
- 20189200余超 2018-2019-2 移动平台应用开发实践第九周作业
20189200余超 2018-2019-2 移动平台应用开发实践第九周作业 图形和制定视图 Android视图系统.层次关系 Android应用设计和Web应用设计类似,也分前端和后端设计.Andr ...
- 20189200余超 2018-2019-2 移动平台应用开发实践作项目代码分析
20189200余超 2018-2019-2 移动平台应用开发实践作项目代码分析 项目名称 小说阅读器 项目功能 注册登录 用户信息.用户密码.用户图像修改 书籍分类 书架 书籍搜索(作者名或书籍名) ...
最新文章
- 【数据分析】百度内部报告解析00后移动互联网行为
- Time to First Byte(TTFB)与Web性能优化
- git分支操作、分支合并冲突解决
- 八、朴素贝叶斯中文分类实战
- android 代码 shape,Android Shape控件美化实现代码
- 国外著名java技术资料网站
- 写在弥勒宝贝两周年之际
- ioc控制反转_深入理解依赖注入(DI)和控制反转(IOC)
- maven+springmvc出现:java.sql.SQLException: Unknown system variable 'query_cache_size'
- 光伏发电系统最大功率点跟踪MPPT matlab/simulink仿真 扰动观察法
- Python2.7打包的exe文件反编译成py文件
- MATLAB含有绝对值的线性规划,Lingo求解带绝对值的线性规划模型
- 把计算机怎么连接手机的网络助手在哪里,怎么将手机网络通过USB共享给电脑
- 经纬度差和米单位的换算
- Kalman详尽原理介绍合集
- 获取DOM元素后,对NodeList的遍历的几种方法
- 刷题日记 acwing 2058笨拙的手指 位运算的运用,迭代器的使用,秦九稍(别的进制转化为10进制)
- Decoding tumour phenotype by noninvasive imaging using a quantitative radiomics approach
- 你好,C++(40)7.1 一切指针都是纸老虎:彻底理解指针
- 常用交换机的配置命令
热门文章
- AIT Worldwide Logistics与卡利塔航空建立民航预备队合作伙伴关系
- vad算法 c语言,腾讯视频cKey算法
- ps cs6选择并遮住在哪设置
- 前端下载 “不支持打开该类型文件或文件已损坏“问题
- Centos7安装cuda10.1
- msysgit在Windows上的安装,
- 大学生“挑战杯”创业计划大赛财务分析估算方法与技巧【转】
- pom 文件的project标签报错Failed to read artifact descriptor for xxx:jar
- 图像处理:U-Net中的重叠-切片(Overlap-tile)
- 匿名内部类的定义格式