Android实现SharePreferences和AutoCompletedTextView

开发工具:Andorid Studio 1.3

运行环境:Android 4.4 KitKat

工程内容

  1. 登录界面,使用SharedPreferences记录登陆状态,点击Register按钮,能够将User和Password写入SharedPreferences,写入后使用Toast提示写入成功
  2. 注册账号成功后,输入账号和密码,点击登陆按钮,若账号与密码正确,则跳转到文件操作界面,否则使用Toast提示登陆错误
  3. 文件操作界面返回登录界面时,如果Remember Password CheckBox没有勾上,则Password控件不保存相应的信息,否则将SharedPreferences保存的信息自动填上相应的控件
  4. 使用AutoCompletedTextView实现文件自动提示功能,如果文件存在,则该匹配的文件自动在AutoCompletedTextView下生成
  5. 在FileContent下输入文件的内容,点击Save File后能够自动保存文件,并且文件名自动提示已经更新;点击ReadFile按钮能够自动读取文件保存的数据,并将内容显示在File Content控件下面
  6. 点击Delete File控件能够删除文件,并且文件名自动提示已经更新,重新点击Read File,发现已经不能够读取文件内容了
  7. 检查是否成功生成文件

代码实现

新建一个类Filetils作为工具类,让别的类调用以进行文件操作。主要功能有三点:

  • 保存文件

    使用FileOutputStream把字符串写入到指定文件名的地方,权限设置为仅该程序私有,把String类型转为byte数组类型保存
	public void saveContent(Context context, String fileName, String fileText) {
try {
FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(fileText.getBytes());
fos.close();
Toast.makeText(context, context.getResources().getString(R.string.msgSaveSuc), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(context, context.getResources().getString(R.string.msgSaveFail), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
  • 读取文件

    使用FileInputStream从指定地方读取文件,写入到一个byte数组中,用byte数组为构造参数构建String类型返回
public String getContent(Context context, String fileName) {
try{
FileInputStream fis = context.openFileInput(fileName);
byte[] contents = new byte[fis.available()];
fis.read(contents);
fis.close();
Toast.makeText(context, context.getResources().getString(R.string.msgReadSuc), Toast.LENGTH_SHORT).show();
return new String(contents);
} catch (IOException e) {
Toast.makeText(context, context.getResources().getString(R.string.msgReadFail), Toast.LENGTH_SHORT).show();
e.printStackTrace();
return new String("");
}
}
  • 删除文件

    用Context对象中的deleteFile()方法删除指定文件名即可
public void deleteFile(Context context, String fileName) {
context.deleteFile(fileName);
Toast.makeText(context, context.getResources().getString(R.string.msgDelSuc), Toast.LENGTH_SHORT).show();
}

为每个界面的按钮设置响应函数

注册按钮点击响应函数:

使用SharedPreferences对象的Editor对象操作保存数据,每次保存后必须提交一遍,提示注册语

Button btnRegister = (Button)this.findViewById(R.id.btnRegister);
btnRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
String usr = edtUsr.getText().toString();
String pwd = edtPwd.getText().toString();
if(usr.isEmpty() || pwd.isEmpty()) {
throw new Exception();
}
editor.putString("username", usr);
editor.putString("password", pwd);
editor.commit();
Toast.makeText(getApplicationContext(), getResources().getString(R.string.msgRegSuc), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), getResources().getString(R.string.msgRegFail), Toast.LENGTH_SHORT).show();
}
}
});

登陆按钮点击响应函数:

判断username和password是否和使用SharedPreferences保存的内容相同,如相同,则新建一个Intent对象跳转页面,并设置字段为空,finish掉当前页面,提示登录语

final Button btnLogin = (Button)this.findViewById(R.id.btnLogin);
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String usr = edtUsr.getText().toString();
String pwd = edtPwd.getText().toString();
if(usr.equals(sp.getString("username", null)) && pwd.equals(sp.getString("password", null))) {
Intent intent = new Intent(LoginActivity.this, EditFileActivity.class);
startActivity(intent);
edtUsr.setText("");
edtPwd.setText("");
LoginActivity.this.finish();
} else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.msgLogErr), Toast.LENGTH_SHORT).show();
}
}
});

选择框状态改变响应函数:

使用SharedPreferences记录当前选择状态,如果是选择状态,判断用户名是否和注册的用户名相匹配,如果匹配,则自动填充密码

chboxRem = (CheckBox)this.findViewById(R.id.chboxRemPwd);
chboxRem.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
editor.putBoolean("isChecked", isChecked);
editor.commit();
if(isChecked && edtUsr.getText().toString().equals(sp.getString("username", null))) {
edtPwd.setText(sp.getString("password", null));
}
}
});

保存文件按钮点击响应函数:

使用工具类FileUtil中的saveContent方法保存成文件,然后必须更新AutoCompletedTextView的适配器,(这里使用新数组代替,旧数组会被系统资源回收)

case R.id.btnSaveFile:
fileUtils.saveContent(EditFileActivity.this, fileName.getText().toString(),
fileContent.getText().toString());
fileName.setAdapter(new ArrayAdapter<String>(EditFileActivity.this,
android.R.layout.simple_dropdown_item_1line, EditFileActivity.this.fileList()));
break;

读取文件按钮点击响应函数:

使用工具类FileUtil中的readContent方法读取文件,并将内容设置到fileContent的一个EditText中,如果文件不存在,则返回空内容

case R.id.btnReadFile:
String contents = fileUtils.getContent(EditFileActivity.this, fileName.getText().toString());
fileContent.setText(contents);
break;

删除文件按钮点击相应函数:

使用工具类FileUtil中的deleteContent方法删除指定文件,然后必须更新AutoCompletedTextView的适配器,(这里使用新数组代替,旧数组会被系统资源回收)

case R.id.btnDeleteFile:
fileUtils.deleteFile(EditFileActivity.this, fileName.getText().toString());
fileName.setAdapter(new ArrayAdapter<String>(EditFileActivity.this,
android.R.layout.simple_dropdown_item_1line, EditFileActivity.this.fileList()));
break;

AutoCompletedTextView中Item点击响应函数:

为了提高用户体验,当用户点击Item后应当自动填充所选内容,把系统输入法隐藏,这里使用AutoCompletedTextView中的setOnItemClickListener方法,使用InputMethodManager获取系统服务,检查输入法是否开启状态,如开启,则隐藏输入法

fileName.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
if(imm.isActive()) {
imm.hideSoftInputFromWindow(EditFileActivity.this.getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
}
});

当用户处于文件编辑界面时,点击返回按钮主动注销界面,这里自己重载这个返回按钮响应

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
Intent intent = new Intent(EditFileActivity.this, LoginActivity.class);
startActivity(intent);
EditFileActivity.this.finish();
}
return true;
}

当用户从文件编辑界面回退到登陆界面的时候,如果之前选择了保存密码,则需要将内容填充回相应的区域,否则仅填充用户名,密码字段填充为空,这里使用onResume()函数重载,同时保证checkbox控件也是逻辑同步的

@Override
protected void onResume() {
super.onResume();
if(sp.getBoolean("isChecked", false)) {
edtUsr.setText(sp.getString("username", null));
edtPwd.setText(sp.getString("password", null));
chboxRem.setChecked(true);
} else {
edtUsr.setText(sp.getString("username", null));
edtPwd.setText("");
chboxRem.setChecked(false);
}
}

效果图

初始化界面->填入账号密码(掩码)并选择记住密码->点击登陆正确则跳转页面->输入部分提示

点击读取文件->新建并保存文件->删除文件->重新读取返回失败

返回按钮登陆信息还在(页面已注销了的)->取消记住密码->登陆跳转->返回按钮登陆密码消失

一些总结

  1. 测试的时候由于跳转页面时没有清除当前页面,导致返回原界面的时候用户名和密码都还在,解决方案是跳转页面后,清除用户名和密码两个字段,同时注销页面
  2. 测试AutuCompletedTextView的时候,输入法的响应令人比较苦恼,明明已经自动填充完毕,输入法还处在这个界面,这用户体验不能忍,然后就加入了AutuCompletedTextView的Item点击响应
  3. 还发现一个问题就在于,界面在onResume的时候检测保存的isChecked是否为true,如果为true则填充用户名和密码,但是checkbox的状态并没有更新,例如退出app后重新进入只有username和password是填充了,checkbox并没有,因此修改了上面的onResume函数重载的代码,更加符合实际

工程下载

传送门:下载

Android实现SharePreferences和AutoCompletedTextView的更多相关文章

  1. Android中SharePreferences的简单实现

    Android中提供SharePreferences这种轻量级的数据存储模式,这种模式能够存储少量数据,并能为自身和其他应用提供数据接口.相对于其他数据存储方式,SharePreferences更加轻 ...

  2. Android应用Preference相关及源代码浅析(SharePreferences篇)

    1 前言 在我们开发Android过程中数据的存储会有非常多种解决方式,譬如常见的文件存储.数据库存储.网络云存储等,可是Android系统为咱们提供了更加方便的一种数据存储方式.那就是SharePr ...

  3. RxJava开发精要7 – Schedulers-解决Android主线程问题

    原文出自<RxJava Essentials> 原文作者 : Ivan Morgillo 译文出自 : 开发技术前线 www.devtf.cn 转载声明: 本译文已授权开发者头条享有独家转 ...

  4. Android开发技术周报

    Android开发技术周报 原文  http://androidweekly.cn/android-dev-weekly-issue48/ 教程 深入理解Android之Gradle Gradle是当 ...

  5. Android 面试题 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  6. Android 面试题集 包含答案

    作者:guoxiaoxing 链接: https://github.com/guoxiaoxing/android-interview 本文基于作者采用的MIT协议分发. 手画一下Android系统架 ...

  7. SharedPreferences 原理 源码 进程间通信 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  8. Android数据存储的三种方式:SharePreferences , file , SQLite

    (1)SharePreferences: 存入: SharedPreferences setter = this.getSharedPreferences("spfile", 0) ...

  9. Android数据的四种存储方式SharedPreferences、SQLite、Content Provider和File (三) —— SharePreferences

    除了SQLite数据库外,SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息.其存储位置在/data ...

随机推荐

  1. ANTLR4权威参考手册

    ANTLR4权威参考手册(一) - 活在当下 乐在其中 - 博客频道 - CSDN.NET ANTLR4权威参考手册

  2. 纯CSS气泡框实现方法探究

    气泡框(或者提示框)是网页中一种很常见的元素,大多用来展示提示信息,如下图所示: 拆分来看,形如这种气泡框无外乎就是一个矩形框+一个指示方向的三角形小箭头,要制作出这样的气泡框,如果解决了三角形小箭头 ...

  3. React模板

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Unieap3.5错误收集

    String index out of range:32 错误描述:Drm查询报错(drm解析报不通过,后台未打印sql) 错误原因:查询SQL中包含字符 <> ,一般用于查询条件 A & ...

  5. UIButton设置imgae图片自适应button的大小且不变形

    在某些情况下,我们使用的UIButton的背景图片不一定就是标准的尺寸,有时会偏大,那么怎么办? 这个比较简单直接设置 :    self.imageView.contentMode = UIView ...

  6. jquery导航二级栏目下拉

    <div class="Nav_L L"> <ul> <li><a href="" title="" ...

  7. 【转】一个高端.NET技术人才的2014年度总结

    [转]一个高端.NET技术人才的2014年度总结  本人在一家公司做技术负责人.主要从事的是.net方面的开发与管理,偏重开发. 弹指一挥间,时间飘然而过,转眼又是一年. 回顾2014年,是我人生中最 ...

  8. 在Array原型链上扩展remove,contain等方法所遇到的坑

    相信jser兄弟们肯定会碰到这样一个问题, 在做数组类的操作的时候,会要求删除数组中的一个元素:亦或是判断某值是否存在于这个数组: OK,拿删除数组元素举例,扩展方法为: Array.prototyp ...

  9. 【转】IE11的变化

    1.navigator.userAgent中不再包含“MSIE”关键字 2.用javascript的判断是否是IE11的方法是: var isIE11 = (sUserAgent.toLowerCas ...

  10. 实现QQ机器人报警

    如题,废话不说,直接上代码.首先是登录QQ的小脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ...