ANDROID基础学习笔记_3_登录和保存数据
来源:互联网 发布:常熟淘宝摄影培训 编辑:程序博客网 时间:2024/06/05 23:56
对于一款软件产品,首先呈现给用户的应该是登录界面,所以今天我来简单的做一个登录界面。
整个界面布局我设计成了
这样。它主要用了一个线性布局和相对布局的组合,LinearLayout属性android:orientation设置成vertical。里面放置两个文本控件,两个输入框控件,再嵌套一个相对布局标签RelativeLayout来布置记住密码的CheckBox和登录Button。或许用表格布局也比较容易。
在做密码输入框时用到了一个inputType属性,将它的值设置成textPassword,另外我还看到了很多其他属性值比如numberPassword,phone,datetime等等。
而对于记住密码复选框,用到了android:checked属性,属性值为true。以此来实现了打开界面默认选中记住密码。以下是.xml文件源码:
<LinearLayout 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:orientation="vertical" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="请输入用户名" /> <EditText android:id="@+id/UserName" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="请输入密码" /> <!-- 通过android:inputType来实现密码输入框 --> <EditText android:id="@+id/PassWord" android:inputType="textPassword" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <!-- 通过CheckBox标签的android:checked=true来实现记住密码 --> <CheckBox android:id="@+id/rememberPwd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="记住密码" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="登录" android:onClick="login" /> </RelativeLayout></LinearLayout>
在后台代码里,我们需要实现按钮的点击事件login,事件里面首先要判断用户名和密码输入框是否为空。然后判断用户名是否存在,不存在返回存在继续判断密码是否正确,密码正确在判断是否选中了保存密码,如果选中就执行保存方法,反之不执行。最后执行登录成功后的操作。这些过程无非是进行了若干个if判断,只要把逻辑关系捋顺了,应该没什么难度。
由于没有学习到在安卓上如何连接数据库或服务器,所以我的代码只是模拟的实现了验证用户名和密码的功能。但是在保存用户名和密码这个功能上,我又学习了如何在指定路径下生成文件。
1. 首先,需要创建一个方法saveUserInfo用来保存用户名和密码,传递了三个参数,除了用户名和密码外还有一个context(上下文)。对于这个单词,我在学习JAVA的servlet的时候就接触过,也知道这么一个意为上下文的单词,但是从字面意思上我始终不能理解上下文到底有什么用。这一次有幸算是稍微了解了一点点吧,上下文就是一个可以获取周围环境内容的这么一个类。具体更深层次的讲,其实我也不是很清楚了。。。
2. 然后接着就是创建文件,在context里有一个方法getFilesDir()可以获取到当前应用程序包下的files文件夹(如果没有,就会被创建),我们就指定将文件建立在这个路径下。(另外还有一个方法可以获取cache文件夹,这里面是用来存放缓存文件的,如果清理应用缓存,cache文件夹下的文件会被清理)
3. 最后就是创建输出流,将用户名和密码写到文件里,关闭输出流。
相应的源代码也是比较简单:
public static boolean saveUserInfo(Context context, String unm, String pwd){//context.getFilesDir();//返回一个路径/data/data/包名/files///context.getCacheDir();//返回一个路径/data/data/包名/catch/File file = new File(context.getFilesDir(),"info.txt");try {FileOutputStream fos = new FileOutputStream(file);fos.write((unm+"####"+pwd).getBytes());fos.close();return true;} catch (Exception e) {e.printStackTrace();return false;}}同时,我们可以把这个方法和另外一个(模拟)获取所有用户名密码的方法写到一个类里方便以后调用。
通过文件输入流获取文件内容的代码是:
public static Map<String, String> getUserInfo(Context context){File file = new File(context.getFilesDir(),"info.txt");try {FileInputStream fis = new FileInputStream(file);BufferedReader br = new BufferedReader(new InputStreamReader(fis));String str = br.readLine();String[] infos = str.split("####");Map<String, String> map = new HashMap<String, String>();map.put("userName", infos[0]);map.put("passWord", infos[1]);return map;} catch (Exception e) {e.printStackTrace();return null;}}关于文件的读取FileInputStream类我上网查的它是针对文件以二进制流读取,而BufferedReader不是只针对文件的,读取形式也不是二进制。
保存数据到sd卡
和保存到手机一样,只不过是更换了一个路径。用到了另外一个类:Environment类,其中有一个静态方法可以获取外部存储空间路径:getExternalStorageDirectory(),返回File。在创建文件的时候将这个file做参数传递,命名文件后即可在sd卡上创建一个文件。
但是如果手机没有sd卡,在保存的时候想必肯定会报错。所以在创建文件之前,我们需要判断sd卡是否存在。同样还是用到了Environment这个类,静态方法getExternalStorageState()来获取sd卡的状态,其返回的参数多样且都在Environment类里设置成了字符串常量,我从网上拷来了它们的解释:
MEDIA_BAD_REMOVAL 在没有挂载前存储媒体已经被移除。
MEDIA_CHECKING 正在检查存储媒体。
MEDIA_MOUNTED 存储媒体已经挂载,并且挂载点可读/写。
MEDIA_MOUNTED_READ_ONLY 存储媒体已经挂载,挂载点只读。
MEDIA_NOFS 存储媒体是空白或是不支持的文件系统。
MEDIA_REMOVED 存储媒体被移除。
MEDIA_SHARED 存储媒体正在通过USB共享。
MEDIA_UNMOUNTABLE 存储媒体无法挂载。
MEDIA_UNMOUNTED 存储媒体没有挂载。
很显然我们用到的是MEDIA_MOUNTED这个,所以整个保存到sd卡的代码如下:
//获取外部存储目录File file = new File(Environment.getExternalStorageDirectory(),"info.txt");try {//获取外部存取器状态if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){FileOutputStream fos = new FileOutputStream(file);fos.write((unm+"####"+pwd).getBytes());fos.close();return true;}else{Toast.makeText(context, "sd卡不可用", Toast.LENGTH_SHORT);return false;}} catch (Exception e) {e.printStackTrace();return false;}关于Environment类在网上找到的详解:传送门
获取手机内部/外部存储空间和可用空间
又用到了一个新类StatFs,我在网上找了半天发现没有合适的,好像所有的博客或资料都在介绍怎样用它来获取存储空间大小,由此可见,也许它的作用仅限于此了。
还是先通过Environment.getExternalStorageDirectory()获取外部存储路径。
然后创建一个StatFs类的实例,用获取的文件的路径字符串做参数:StatFs stat = new StatFs(path.getPath())。
接下来是用getBlockSize()获取单个block的大小。我始终找不到对于这个东西的解释,或许就是单纯的一个存储块吧。
相应的就可以获取总存储块数getBlockCount()以及可用存储块数getAvailableBlocks(),将这些块数和单个存储块大小相乘,即可获得最终的总容量和可用容量。
最后我们还需要做进一步的转化,因为相乘之后的结果是长整型的字节,转换成我们常见的k/m/g/t等。
而获取内部存储空间方法大致相同,只是在一开始获取路径的方法不同:Environment.getDataDirectory()。具体代码如下:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = (TextView) findViewById(R.id.tv);//获取外部存储路径File path = Environment.getExternalStorageDirectory();//StatFs获取的都是以block为单位的StatFs stat = new StatFs(path.getPath());//得到单个block的大小long bolckSize = stat.getBlockSize();//获取所有数据块数long totalBlocks = stat.getBlockCount();//获取可用数据块数long availableBlocks = stat.getAvailableBlocks();long totalSize = bolckSize*totalBlocks;long availSize = availableBlocks*bolckSize;String totalStr = Formatter.formatFileSize(this, totalSize);String availStr = Formatter.formatFileSize(this, availSize);tv.setText("totalSize:"+totalSize+"\navailSize:"+availSize+"\n总容量:"+totalStr+"\n可用容量"+availStr+"\n"+getRomSpaceInfo());}public String getRomSpaceInfo(){File path = Environment.getDataDirectory();StatFs stat = new StatFs(path.getPath());long bolckSize = stat.getBlockSize();long totalBlocks = stat.getBlockCount();long availableBlocks = stat.getAvailableBlocks();long totalSize = bolckSize*totalBlocks;long availSize = availableBlocks*bolckSize;String totalStr = Formatter.formatFileSize(this, totalSize);String availStr = Formatter.formatFileSize(this, availSize);return "手机存储总空间:"+totalStr+"\n手机存储可用空间:"+availStr;}看似复杂,其实重要的代码不超过十行。
最近发现自己学东西有一种小题大做的感觉,一篇博文写下来,感觉有营养的代码真的是少之又少。经验不足的菜鸟啊,还得多看看别人的博文是怎么写的。
找到一篇比较好的介绍数据存储的博文,前往围观
紧接着,我又学了一种保存信息的方式:用SharedPreferences类来保存和获取信息。
保存信息:
通过上下文这个类里的getSharedPreferences()方法,我们可以创建出来一个.xml文件,它被创建在了当前环境下新建的sharePre文件夹下,返回一个SharedPreferences类型的实例sp。
然后调用sp的edit()方法得到编辑器,返回的是一个Editor类型实例editor。
然后调用editor的putString()方法,就可以像使用map一样,包用户名,密码等数据以.xml文件保存起来。
同样的,还可以调用putBoolean()putInt()putLong()等方法,存储相应类型的数据。
在最后注意这样一行代码:editor.commit();它的意义在于确保数据的同时提交,假如保存过程中报错,那么这条代码可以保证数据回滚,恢复之前的操作,类似于数据库的事务。具体代码如下:
SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);//得到sp的编辑器Editor editor = sp.edit();editor.putString("userName", unm);editor.putString("passWord", pwd);//类似数据库的事务,保证数据同时提交editor.commit();获取信息:
非常简单的一条代码:sp.getString("userName", "");
之所以要传递两个参数,是为了保证如果在文件中没有找到键相对应的值,那么会返回一个默认值,类似于数据库里isnull(mycount,0)这样的用法。
好吧,我承认,这是我好几天学的东西组合到了一起,真的是有点乱啊。。。
- ANDROID基础学习笔记_3_登录和保存数据
- Android学习笔记_3_四种布局
- C++ Primer 学习笔记_3_变量和基本类型
- JS学习笔记_3_数组
- Android学习(19) -- 数据存储之File (简单登录保存用户名和密码)
- Android学习笔记(十七)数据保存
- SQL基础操作_3_数据字典
- Android-SharedPreferences保存登录数据
- ucos2学习笔记_3_内核架构
- Java学习笔记_3_包中类的使用
- 简明Python教程学习笔记_3_模块
- Android 学习笔记之实时保存数据-现场保护
- Android 学习笔记之实时保存数据-现场保护 onSaveInstanceState()
- Spark学习笔记——数据读取和保存
- android笔记--保存和恢复activity的状态数据
- android笔记--保存和恢复activity的状态数据
- android笔记--保存和恢复activity的状态数据
- android笔记--保存和恢复activity的状态数据
- cloudera cdh sqoop2 加入myqsl 驱动包
- AppCan技术风暴来袭,12城13场免费培训火速报名中
- 央视“大裤衩”首次清洗:花50万
- leetcode || 78、Subsets
- dirs\pushd\popd命令用法
- ANDROID基础学习笔记_3_登录和保存数据
- NSPredicate
- STL中的set容器的一点总结
- 山东省出台《意见》配置公共体育设施
- 题目:字符串删除数字大写变小写
- Linux Shell 替换
- 最大熵开源——openNLP MaxEnt
- android 发短信 和 接收 短信
- ASP.NET性能优化之让浏览器缓存动态网页