SharedPreferences用法:
ShareWriteActivity.java:
public class ShareWriteActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_name;
private EditText et_age;
private EditText et_height;
private EditText et_weight;
private CheckBox ck_married;
private Button btn_share;
private SharedPreferences preferences;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_share_write);
et_name = findViewById(R.id.et_name);
et_age = findViewById(R.id.et_age);
et_height = findViewById(R.id.et_height);
et_weight = findViewById(R.id.et_weight);
ck_married = findViewById(R.id.ck_married);
btn_share = findViewById(R.id.btn_share);
btn_share.setOnClickListener(this);
//生成config.xml文件
preferences = getSharedPreferences("config", Context.MODE_PRIVATE);
//重新打开app,读取config.xml
reload();
}
private void reload() {
String name = preferences.getString("name", null);
if(name != null){
et_name.setText(name);
}
int age = preferences.getInt("age", 0);
if(age != 0){
et_age.setText(String.valueOf(age));
}
float height = preferences.getFloat("height", 0f);
if(height != 0f){
et_height.setText(String.valueOf(height));
}
float weight = preferences.getFloat("weight", 0f);
if(weight != 0f){
et_weight.setText(String.valueOf(weight));
}
boolean married = preferences.getBoolean("married", false);
ck_married.setChecked(married);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_share:
String name = et_name.getText().toString();
String age = et_age.getText().toString();
String height = et_height.getText().toString();
String weight = et_weight.getText().toString();
//获取编辑器
SharedPreferences.Editor editor = preferences.edit();
editor.putString("name",name);
editor.putInt("age", Integer.parseInt(age));
editor.putFloat("height", Float.parseFloat(height));
editor.putFloat("weight", Float.parseFloat(weight));
editor.putBoolean("married",ck_married.isChecked());
//提交编辑信息
editor.commit();
break;
}
}
}
lactivity_share_write.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:padding="3dp">
<TextView
android:textColor="@color/black"
android:textSize="18sp"
android:text="@string/name"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<EditText
android:id="@+id/et_name"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="@drawable/edittest_selector"
android:hint="@string/input_name"
android:inputType="text"
android:textSize="18sp"
android:textColorHint="@color/grey"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:padding="3dp">
<TextView
android:textColor="@color/black"
android:textSize="18sp"
android:text="@string/age"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<EditText
android:id="@+id/et_age"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="@drawable/edittest_selector"
android:hint="@string/input_age"
android:inputType="text"
android:textSize="18sp"
android:textColorHint="@color/grey"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:padding="3dp">
<TextView
android:textColor="@color/black"
android:textSize="18sp"
android:text="@string/height"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<EditText
android:id="@+id/et_height"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="@drawable/edittest_selector"
android:hint="@string/input_height"
android:inputType="text"
android:textSize="18sp"
android:textColorHint="@color/grey"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:padding="3dp">
<TextView
android:textColor="@color/black"
android:textSize="18sp"
android:text="@string/weight"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<EditText
android:id="@+id/et_weight"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="@drawable/edittest_selector"
android:hint="@string/input_weight"
android:inputType="text"
android:textSize="18sp"
android:textColorHint="@color/grey"/>
</LinearLayout>
<CheckBox
android:id="@+id/ck_married"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/married"
android:textSize="18sp"
android:textColor="@color/black"/>
<Button
android:id="@+id/btn_share"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/share_preference"/>
</LinearLayout>
点击保存,在Device File Explorer->data->data->对应的包下->shared_prefs->config.xml,将其保存到本地D盘下
杀掉当前进程,重新进入,会重新读取config.xml文件信息,并显示在界面中,修改后保存后,xml内信息更新。
总结步骤:
1.获取sharedPreferences对象
2.如果保存密码被勾选(或其他条件满足),获取sharedPreferences的编辑器
3.通过编辑器put每个editTest中填写的值,提交编辑信息(commit)
4.重新进入时,读取上次保存的信息,(如果xml文件中保存密码是被选中的,读取xml文件信息,并set到对应的editTest里)
数据库的创建和删除: (关于数据库操作,后面采用Room框架,这里可不看)
创建:在data/data/对应包下的file文件夹下生成db文件
mDatabaseName = getFilesDir() + "/test.db";
SQLiteDatabase db = openOrCreateDatabase(mDatabaseName, Context.MODE_PRIVATE, null);
desc = String.format("数据库%s创建%s",db.getPath(),(db!=null)?"成功":"失败");
tv_content.setText(desc);
删除:
mDatabaseName = getFilesDir() + "/test.db";
boolean result = deleteDatabase(mDatabaseName);
desc = String.format("数据库%s删除%s",mDatabaseName,result?"成功":"失败");
tv_content.setText(desc);
数据的增删改查
获取读写连接等准备:
//使用单例模式,构造函数用private修饰
private UserDBHelper(@Nullable Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
//利用单例模式获取数据库帮助器的唯一实例
public static UserDBHelper getInstance(Context context){
if(mHelper == null){
mHelper = new UserDBHelper(context);
}
return mHelper;
}
//打开数据库的读连接
public SQLiteDatabase openReadLink(){
if(mRDB == null || !mRDB.isOpen()){
mRDB = mHelper.getReadableDatabase();
}
return mRDB;
}
//打开数据库的读连接
public SQLiteDatabase openWriteLink(){
if(mWDB == null || !mWDB.isOpen()){
mWDB = mHelper.getWritableDatabase();
}
return mWDB;
}
//关闭数据库连接
public void closeLink(){
if(mRDB != null && mRDB.isOpen()){
mRDB.close();
mRDB = null;
}
if(mWDB != null && mWDB.isOpen()){
mWDB.close();
mWDB = null;
}
}
//创建数据库,执行建表语句
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
" name VARCHAR NOT NULL," +
" age INTEGER NOT NULL," +
" height LONG NOT NULL," +
" weight FLOAT NOT NULL," +
" married INTEGER NOT NULL);";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
添加:
public long insert(User user){
ContentValues values = new ContentValues();
values.put("name",user.name);
values.put("age",user.age);
values.put("height",user.height);
values.put("weight",user.weight);
values.put("married",user.married);
//insert(String table, String nullColumnHack, ContentValues values)
//如果第三个参数values为null或者元素个数为0,由于insert()方法要求必须添加一条除了主键之外其他字段为null值的记录,
// 如:insert into person() values(),在添加数据时什么值都没给,左边的sql语句不满足标准sql的语法
//为了满足sql的语法,insert语句必须给定一个字段,则语句变成:insert into person(name) values(NULL)
//该字段要求为非主键
//当第三个参数不为null,并且元素个数大于0时,可以把第二个参数设置为null
return mWDB.insert(TABLE_NAME,null,values);
}
删除:
public long deleteByName(String name){
//删除所有
//mWDB.delete(TABLE_NAME,"1=1",null);
//第三个参数就是第二个参数中的问号,有几个问号,String数组传几个值
return mWDB.delete(TABLE_NAME,"name = ?",new String[]{name});
}
更新:
public long updateByName(User user){
ContentValues values = new ContentValues();
values.put("name",user.name);
values.put("age",user.age);
values.put("height",user.height);
values.put("weight",user.weight);
values.put("married",user.married);
return mWDB.update(TABLE_NAME,values,"name = ?",new String[]{user.name});
}
查询:
public List<User> queryAll(){
List<User> list = new ArrayList<>();
//执行记录查询动作,该语句返回结果集的游标
Cursor cursor = mRDB.query(TABLE_NAME,null,null,null,null,null,null);
while(cursor.moveToNext()){
User user = new User();
user.id = cursor.getInt(0);
user.name = cursor.getString(1);
user.age = cursor.getInt(2);
user.height = cursor.getLong(3);
user.weight = cursor.getFloat(4);
//SQLite没有Boolean类型,用0表示false,用1表示true
user.married = (cursor.getInt(5) != 0);
list.add(user);
}
return list;
}
public List<User> queryByName(String name){
List<User> list = new ArrayList<>();
//执行记录查询动作,该语句返回结果集的游标
Cursor cursor = mRDB.query(TABLE_NAME,null,"name = ?",new String[]{name},null,null,null);
while(cursor.moveToNext()){
User user = new User();
user.id = cursor.getInt(0);
user.name = cursor.getString(1);
user.age = cursor.getInt(2);
user.height = cursor.getLong(3);
user.weight = cursor.getFloat(4);
//SQLite没有Boolean类型,用0表示false,用1表示true
user.married = (cursor.getInt(5) != 0);
list.add(user);
}
return list;
}
事务:
try {
mWDB.beginTransaction();
mWDB.insert(TABLE_NAME, null, values);
int i = 10 / 0;
mWDB.insert(TABLE_NAME, null, values);
mWDB.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
mWDB.endTransaction();
}
完整代码:
User.java:
public class User {
public int id;
public String name;
public int age;
public long height;
public float weight;
public boolean married;
public User(){
}
public User(String name, int age, long height, float weight, boolean married) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
this.married = married;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", height=" + height +
", weight=" + weight +
", married=" + married +
'}';
}
}
UserDBHelper.java:
public class UserDBHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "user.db";
public static final String TABLE_NAME = "user_info";
public static final int DB_VERSION = 1;
public static UserDBHelper mHelper = null;
private SQLiteDatabase mRDB = null;
private SQLiteDatabase mWDB = null;
//使用单例模式,构造函数用private修饰
private UserDBHelper(@Nullable Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
//利用单例模式获取数据库帮助器的唯一实例
public static UserDBHelper getInstance(Context context) {
if (mHelper == null) {
mHelper = new UserDBHelper(context);
}
return mHelper;
}
//打开数据库的读连接
public SQLiteDatabase openReadLink() {
if (mRDB == null || !mRDB.isOpen()) {
mRDB = mHelper.getReadableDatabase();
}
return mRDB;
}
//打开数据库的读连接
public SQLiteDatabase openWriteLink() {
if (mWDB == null || !mWDB.isOpen()) {
mWDB = mHelper.getWritableDatabase();
}
return mWDB;
}
//关闭数据库连接
public void closeLink() {
if (mRDB != null && mRDB.isOpen()) {
mRDB.close();
mRDB = null;
}
if (mWDB != null && mWDB.isOpen()) {
mWDB.close();
mWDB = null;
}
}
//创建数据库,执行建表语句
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
" name VARCHAR NOT NULL," +
" age INTEGER NOT NULL," +
" height LONG NOT NULL," +
" weight FLOAT NOT NULL," +
" married INTEGER NOT NULL);";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//数据库版本升级
String sql = "ALTER TABLE "+ TABLE_NAME + " ADD COLUMN phone VARCHAR;";
db.execSQL(sql);
sql = "ALTER TABLE "+ TABLE_NAME + " ADD COLUMN password VARCHAR;";
db.execSQL(sql);
}
public long insert(User user) {
ContentValues values = new ContentValues();
values.put("name", user.name);
values.put("age", user.age);
values.put("height", user.height);
values.put("weight", user.weight);
values.put("married", user.married);
//insert(String table, String nullColumnHack, ContentValues values)
//如果第三个参数values为null或者元素个数为0,由于insert()方法要求必须添加一条除了主键之外其他字段为null值的记录,
// 如:insert into person() values(),在添加数据时什么值都没给,左边的sql语句不满足标准sql的语法
//为了满足sql的语法,insert语句必须给定一个字段,则语句变成:insert into person(name) values(NULL)
//该字段要求为非主键
//当第三个参数不为null,并且元素个数大于0时,可以把第二个参数设置为null
return mWDB.insert(TABLE_NAME,null,values);
}
public long deleteByName(String name) {
//删除所有
// mWDB.delete(TABLE_NAME,"1=1",null);
//第三个参数就是第二个参数中的问号,有几个问号,String数组传几个值
return mWDB.delete(TABLE_NAME, "name = ?", new String[]{name});
}
public long updateByName(User user) {
ContentValues values = new ContentValues();
values.put("name", user.name);
values.put("age", user.age);
values.put("height", user.height);
values.put("weight", user.weight);
values.put("married", user.married);
return mWDB.update(TABLE_NAME, values, "name = ?", new String[]{user.name});
}
public List<User> queryAll() {
List<User> list = new ArrayList<>();
//执行记录查询动作,该语句返回结果集的游标
Cursor cursor = mRDB.query(TABLE_NAME, null, null, null, null, null, null);
while (cursor.moveToNext()) {
User user = new User();
user.id = cursor.getInt(0);
user.name = cursor.getString(1);
user.age = cursor.getInt(2);
user.height = cursor.getLong(3);
user.weight = cursor.getFloat(4);
//SQLite没有Boolean类型,用0表示false,用1表示true
user.married = (cursor.getInt(5) != 0);
list.add(user);
}
return list;
}
public List<User> queryByName(String name) {
List<User> list = new ArrayList<>();
//执行记录查询动作,该语句返回结果集的游标
Cursor cursor = mRDB.query(TABLE_NAME, null, "name = ?", new String[]{name}, null, null, null);
while (cursor.moveToNext()) {
User user = new User();
user.id = cursor.getInt(0);
user.name = cursor.getString(1);
user.age = cursor.getInt(2);
user.height = cursor.getLong(3);
user.weight = cursor.getFloat(4);
//SQLite没有Boolean类型,用0表示false,用1表示true
user.married = (cursor.getInt(5) != 0);
list.add(user);
}
return list;
}
}
SQLiteHelperActivity.java:
public class SQLiteHelperActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_name;
private EditText et_age;
private EditText et_weight;
private EditText et_height;
private CheckBox ck_married;
private UserDBHelper mHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_helper);
et_name = findViewById(R.id.et_name);
et_age = findViewById(R.id.et_age);
et_weight = findViewById(R.id.et_weight);
et_height = findViewById(R.id.et_height);
ck_married = findViewById(R.id.ck_married);
findViewById(R.id.btn_add).setOnClickListener(this);
findViewById(R.id.btn_delete).setOnClickListener(this);
findViewById(R.id.btn_update).setOnClickListener(this);
findViewById(R.id.btn_select).setOnClickListener(this);
findViewById(R.id.btn_reset).setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
//获取数据库帮助器的实例
mHelper = UserDBHelper.getInstance(this);
//打开数据库帮助器的读写连接
mHelper.openWriteLink();
mHelper.openReadLink();
}
@Override
protected void onStop() {
super.onStop();
mHelper.closeLink();
}
@Override
public void onClick(View v) {
String name = et_name.getText().toString();
String age = et_age.getText().toString();
String height = et_height.getText().toString();
String weight = et_weight.getText().toString();
Boolean married = ck_married.isChecked();
User user = null;
switch (v.getId()) {
case R.id.btn_add:
user = new User(name,
Integer.parseInt(age),
Long.parseLong(height),
Float.parseFloat(weight),
married);
if (mHelper.insert(user) > 0) {
ToastUtil.show(this, "添加成功");
}
break;
case R.id.btn_delete:
if (mHelper.deleteByName(name) > 0) {
ToastUtil.show(this, "删除成功");
}
break;
case R.id.btn_update:
user = new User(name,
Integer.parseInt(age),
Long.parseLong(height),
Float.parseFloat(weight),
married);
if (mHelper.updateByName(user) > 0) {
ToastUtil.show(this, "修改成功");
}
break;
case R.id.btn_select:
List<User> list = mHelper.queryByName(name);
for(User u : list){
Log.d("ning",u.toString());
}
break;
case R.id.btn_reset:
et_name.setText(null);
et_age.setText(null);
et_height.setText(null);
et_weight.setText(null);
ck_married.setChecked(false);
ToastUtil.show(this,"重置成功");
break;
}
}
}
public static void show(Context context, String desc){
Toast.makeText(context,desc,Toast.LENGTH_SHORT).show();
}
对记住密码的优化:
LoginSQLiteActivity.java:
public class LoginSQLiteActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener, View.OnClickListener, View.OnFocusChangeListener {
private RadioGroup rg_login;
private TextView tv_password;
private EditText et_password;
private Button btn_forget;
private CheckBox ck_remember;
private EditText et_phone;
private RadioButton rb_verifycode;
private RadioButton rb_password;
private ActivityResultLauncher<Intent> register;
private Button btn_login;
private String mPassword="111111";
private String mVerifyCode;
private LoginDBHelper mHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login_main);
rg_login = findViewById(R.id.rg_login);
rg_login.setOnCheckedChangeListener(this);
tv_password = findViewById(R.id.tv_password);
et_password = findViewById(R.id.et_password);
et_phone = findViewById(R.id.et_phone);
btn_forget = findViewById(R.id.btn_forget);
btn_forget.setOnClickListener(this);
ck_remember = findViewById(R.id.ck_remember);
et_password.addTextChangedListener(new HideTextWatcher(et_password,6));
et_phone.addTextChangedListener(new HideTextWatcher(et_phone,11));
rb_password = findViewById(R.id.rb_password);
rb_verifycode = findViewById(R.id.rb_verifycode);
btn_login = findViewById(R.id.btn_login);
btn_login.setOnClickListener(this);
register = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
Intent intent = result.getData();
if(intent != null && result.getResultCode() == Activity.RESULT_OK){
mPassword = intent.getStringExtra("new_password");
}
}
});
et_password.setOnFocusChangeListener(this);
}
private void reload() {
LoginInfo info = mHelper.queryTop();
if(info != null && info.remember){
et_phone.setText(info.phone);
et_password.setText(info.password);
ck_remember.setChecked(true);
}
}
@Override
protected void onStart() {
super.onStart();
mHelper = LoginDBHelper.getInstance(this);
mHelper.openReadLink();
mHelper.openWriteLink();
reload();
}
@Override
protected void onStop() {
super.onStop();
mHelper.closeLink();
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_password:
tv_password.setText(getString(R.string.login_password));
et_password.setHint(getString(R.string.input_password));
btn_forget.setText(getString(R.string.forget_password));
ck_remember.setVisibility(View.VISIBLE);
break;
case R.id.rb_verifycode:
tv_password.setText(getString(R.string.verifycode));
et_password.setHint(getString(R.string.inpout_verifycode));
btn_forget.setText(getString(R.string.get_verifycode));
ck_remember.setVisibility(View.GONE);
break;
}
}
@SuppressLint({"DefaultLocale", "NonConstantResourceId"})
@Override
public void onClick(View v) {
String phone = et_phone.getText().toString();
if(phone.length()<11){
Toast.makeText(this,"请输入正确的手机号",Toast.LENGTH_LONG).show();
return;
}
switch(v.getId()){
case R.id.btn_forget:
//选择了密码方式校验,此时要跳到找回密码页面
if (rb_password.isChecked()){
Intent intent = new Intent(this, LoginForgetActivity.class);
intent.putExtra("phone",phone);
register.launch(intent);
}else if(rb_verifycode.isChecked()){
//生成六位数,范围是0-999999,如果生成位数不满6位,用0代替
mVerifyCode = String.format("%06d",new Random().nextInt(999999));
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("请记住验证码");
builder.setMessage("手机号"+phone+",本次验证码是"+mVerifyCode+",请输入验证码");
builder.setPositiveButton("好的",null);
AlertDialog dialog = builder.create();
dialog.show();
}
break;
case R.id.btn_login:
if(rb_password.isChecked()){
if (!mPassword.equals(et_password.getText().toString())){
Toast.makeText(this,"请输入正确的密码",Toast.LENGTH_LONG).show();
return;
}
}else if (rb_verifycode.isChecked()){
if(!mVerifyCode.equals(et_password.getText().toString())){
Toast.makeText(this,"请输入正确的密码",Toast.LENGTH_LONG).show();
return;
}
}
//提示用户登录成功
loginSuccess();
break;
}
}
private void loginSuccess() {
String desc = String.format("您的手机号码是%s,恭喜你通过登录验证,点击\"确定\"按钮返回上一个页面",et_phone.getText().toString());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("登录成功");
builder.setMessage(desc);
builder.setPositiveButton("确定返回", (dialog, which) -> finish());
builder.setNegativeButton("我再看看",null);
AlertDialog dialog = builder.create();
dialog.show();
//保存到数据库
LoginInfo info = new LoginInfo();
info.phone = et_phone.getText().toString();
info.password = et_password.getText().toString();
info.remember = ck_remember.isChecked();
mHelper.save(info);
}
//当密码输入框获取焦点后,根据输入的电话号码,查询出对应的密码,自动填入
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(v.getId() == R.id.et_password && hasFocus){
LoginInfo info = mHelper.queryByPhone(et_phone.getText().toString());
if(info != null){
et_password.setText(info.password);
ck_remember.setChecked(info.remember);
}else {
et_password.setText("");
ck_remember.setChecked(false);
}
}
}
//定义一个编辑框监听器,在输入文本达到指定长度时自动隐藏输入法
private class HideTextWatcher implements TextWatcher {
private int mMaxLength;
private EditText mView;
public HideTextWatcher(EditText v, int maxLength) {
this.mMaxLength = maxLength;
this.mView = v;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String str = s.toString();
if(str.length() == mMaxLength){
ViewUtil.hideOneInputMethod(LoginSQLiteActivity.this,mView);
}
}
}
}
LoginDBHelper.java:
public class LoginDBHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "login.db";
public static final String TABLE_NAME = "login_info";
public static final int DB_VERSION = 1;
public static LoginDBHelper mHelper = null;
private SQLiteDatabase mRDB = null;
private SQLiteDatabase mWDB = null;
//使用单例模式,构造函数用private修饰
private LoginDBHelper(@Nullable Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
//利用单例模式获取数据库帮助器的唯一实例
public static LoginDBHelper getInstance(Context context) {
if (mHelper == null) {
mHelper = new LoginDBHelper(context);
}
return mHelper;
}
//打开数据库的读连接
public SQLiteDatabase openReadLink() {
if (mRDB == null || !mRDB.isOpen()) {
mRDB = mHelper.getReadableDatabase();
}
return mRDB;
}
//打开数据库的读连接
public SQLiteDatabase openWriteLink() {
if (mWDB == null || !mWDB.isOpen()) {
mWDB = mHelper.getWritableDatabase();
}
return mWDB;
}
//关闭数据库连接
public void closeLink() {
if (mRDB != null && mRDB.isOpen()) {
mRDB.close();
mRDB = null;
}
if (mWDB != null && mWDB.isOpen()) {
mWDB.close();
mWDB = null;
}
}
//创建数据库,执行建表语句
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
" phone VARCHAR NOT NULL," +
" password INTEGER NOT NULL," +
" remember INTEGER NOT NULL);";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void save(LoginInfo info) {
//如果存在则先删除,再添加
//好处是最近一次登录的永远在最上面
try {
mWDB.beginTransaction();
delete(info);
insert(info);
mWDB.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
mWDB.endTransaction();
}
}
public long delete(LoginInfo info) {
return mWDB.delete(TABLE_NAME, "phone = ?", new String[]{info.phone});
}
public long insert(LoginInfo info) {
ContentValues values = new ContentValues();
values.put("phone", info.phone);
values.put("password", info.password);
values.put("remember", info.remember);
return mWDB.insert(TABLE_NAME, null, values);
}
public List<User> queryAll() {
List<User> list = new ArrayList<>();
//执行记录查询动作,该语句返回结果集的游标
Cursor cursor = mRDB.query(TABLE_NAME, null, null, null, null, null, null);
while (cursor.moveToNext()) {
User user = new User();
user.id = cursor.getInt(0);
user.name = cursor.getString(1);
user.age = cursor.getInt(2);
user.height = cursor.getLong(3);
user.weight = cursor.getFloat(4);
//SQLite没有Boolean类型,用0表示false,用1表示true
user.married = (cursor.getInt(5) != 0);
list.add(user);
}
return list;
}
public LoginInfo queryTop() {
LoginInfo info = null;
String sql = "select * from " + TABLE_NAME + " where remember = 1 ORDER BY _id DESC limit 1";
//执行自己拼接的sql语句
Cursor cursor = mRDB.rawQuery(sql, null);
if (cursor.moveToNext()) {
info = new LoginInfo();
info.id = cursor.getInt(0);
info.phone = cursor.getString(1);
info.password = cursor.getString(2);
info.remember = (cursor.getInt(3) != 0);
}
return info;
}
public LoginInfo queryByPhone(String phone) {
LoginInfo info = null;
String sql = "select * from " + TABLE_NAME;
Cursor cursor = mRDB.query(TABLE_NAME, null, "phone = ? and remember = 1", new String[]{phone}, null, null, null);
if (cursor.moveToNext()) {
info = new LoginInfo();
info.id = cursor.getInt(0);
info.phone = cursor.getString(1);
info.password = cursor.getString(2);
info.remember = (cursor.getInt(3) != 0);
}
return info;
}
}
LoginInfo.java:
public class LoginInfo {
public int id;
public String phone;
public String password;
public boolean remember = false;
public LoginInfo(){
}
public LoginInfo(String phone, String password, boolean remember) {
this.phone = phone;
this.password = password;
this.remember = remember;
}
@Override
public String toString() {
return "LoginInfo{" +
"id=" + id +
", phone='" + phone + '\'' +
", password='" + password + '\'' +
", remember=" + remember +
'}';
}
}
存储空间:
外部存储私有空间、外部存储公共空间、内部存储私有空间
FileActivity.java:
public class FileWriteActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_name;
private EditText et_age;
private EditText et_height;
private EditText et_weight;
private CheckBox ck_married;
private Button btn_share;
private String path;
private TextView tv_text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_write);
et_name = findViewById(R.id.et_name);
et_age = findViewById(R.id.et_age);
et_height = findViewById(R.id.et_height);
et_weight = findViewById(R.id.et_weight);
ck_married = findViewById(R.id.ck_married);
btn_share = findViewById(R.id.btn_share);
btn_share.setOnClickListener(this);
findViewById(R.id.btn_read).setOnClickListener(this);
tv_text = findViewById(R.id.tv_read);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_share:
String name = et_name.getText().toString();
String age = et_age.getText().toString();
String height = et_height.getText().toString();
String weight = et_weight.getText().toString();
StringBuilder sb = new StringBuilder();
sb.append("姓名:").append(name);
sb.append("\n年龄:").append(age);
sb.append("\n身高:").append(height);
sb.append("\n体重:").append(weight);
sb.append("\n婚否:").append(ck_married.isChecked()?"是":"否");
String fileName = System.currentTimeMillis() + ".txt";
String directory = null;
//外部存储的私有空间,应用卸载后就没有了
// directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString();
//外部存储的公共空间,应用卸载还在
// directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();
//内部存储私有空间
directory = getFilesDir().toString();
path = directory + File.separatorChar + fileName;
Log.d("syf",path);
FileUtil.saveText(path,sb.toString());
ToastUtil.show(this,"保存成功");
break;
case R.id.btn_read:
tv_text.setText(FileUtil.openText(path));
break;
}
}
}
FileUtil.java:
public class FileUtil {
//把字符串保存到指定路径的文本文件
public static void saveText(String path, String txt) {
BufferedWriter os = null;
try {
os = new BufferedWriter(new FileWriter(path));
os.write(txt);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//从指定路径的文本文件中读取内容字符串
public static String openText(String path) {
BufferedReader is = null;
StringBuilder sb = new StringBuilder();
try {
is = new BufferedReader(new FileReader(path));
String line = null;
while ((line = is.readLine()) != null) {
sb.append(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
保存读取图片:
case R.id.btn_save:
String fileName = System.currentTimeMillis() + ".jepg";
//获取当前APP的私有下载目录
path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + File.separatorChar + fileName;
Log.d("syf",path);
//从指定的资源文件中获取位图对象
Bitmap b1 = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap_1);
FileUtil.saveImage(path,b1);
ToastUtil.show(this,"保存成功");
break;
case R.id.btn_read:
//
// Bitmap b2 = FileUtil.openImage(path);
// ivShow.setImageBitmap(b2);
//
// Bitmap b2 = BitmapFactory.decodeFile(path);
// ivShow.setImageBitmap(b2);
//直接调用setImageURI方法,设置图像视图的路径对象
ivShow.setImageURI(Uri.parse(path));
break;
//把位图数据保存到指定路径的图片文件
public static void saveImage(String path, Bitmap bitmap) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path);
//把位图数据压缩到文件输出流中
bitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//从指定路径的图片文件中读取位图数据
public static Bitmap openImage(String path) {
Bitmap bitmap = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(path);
bitmap = BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bitmap;
}
Application生命周期:
public class MyApplication extends Application {
//在APP启动时调用
@Override
public void onCreate() {
super.onCreate();
Log.d("syf","MyApplication onCreate...");
}
//在App终止时调用,不会有回调,log不会打
@Override
public void onTerminate() {
super.onTerminate();
Log.d("syf","MyApplication onTerminal...");
}
//在配置改变时调用,例如从竖屏变为横屏
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d("syf","MyApplication onConfigurationChanged...");
}
}
在声明文件的application标签中加上
android:name=".MyApplication"
Application全局变量:
public class AppWriteActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_name;
private EditText et_age;
private EditText et_height;
private EditText et_weight;
private CheckBox ck_married;
private MyApplication app;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_write);
et_name = findViewById(R.id.et_name);
et_age = findViewById(R.id.et_age);
et_height = findViewById(R.id.et_height);
et_weight = findViewById(R.id.et_weight);
ck_married = findViewById(R.id.ck_married);
findViewById(R.id.btn_share).setOnClickListener(this);
app = MyApplication.getInstance();
reload();
}
private void reload() {
String name = app.infoMap.get("name");
if(name == null){
return;
}
String age = app.infoMap.get("age");
String height = app.infoMap.get("height");
String weight = app.infoMap.get("weight");
String married = app.infoMap.get("married");
et_name.setText(name);
et_age.setText(age);
et_height.setText(height);
et_weight.setText(weight);
if ("是".equals(married)) {
ck_married.setChecked(true);
} else {
ck_married.setChecked(false);
}
}
@Override
public void onClick(View v) {
String name = et_name.getText().toString();
String age = et_age.getText().toString();
String height = et_height.getText().toString();
String weight = et_weight.getText().toString();
app.infoMap.put("name", name);
app.infoMap.put("age", age);
app.infoMap.put("height", height);
app.infoMap.put("weight", weight);
app.infoMap.put("married", ck_married.isChecked() ? "是" : "否");
}
}
public class MyApplication extends Application {
private static MyApplication mApp;
//声明一个公共的信息映射对象,可当做全局变量使用
public HashMap<String,String> infoMap = new HashMap<>();
public static MyApplication getInstance(){
return mApp;
}
@Override
public void onCreate() {
super.onCreate();
mApp = this;
Log.d("syf","onCreate.....");
}
@Override
public void onTerminate() {
super.onTerminate();
Log.d("syf","onTerminate.....");
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d("syf","onConfigurationChanged.....");
}
}
infoMap中的数据随着App销毁会被清除
使用ROOM框架操作数据库:
1.创建实体类,添加@Entity注解
@Entity
public class Book {
@PrimaryKey(autoGenerate = true)//自动增长
private int id;
private String name;
private String editor;
private String publication;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEditor() {
return editor;
}
public void setEditor(String editor) {
this.editor = editor;
}
public String getPublication() {
return publication;
}
public void setPublication(String publication) {
this.publication = publication;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", editor='" + editor + '\'' +
", publication='" + publication + '\'' +
", money=" + money +
'}';
}
}
2.创建持久化类,添加@Dao注解
@Dao
public interface BookDao {
@Insert
//可变参数,可添加多个参数
void insert(Book... book);
@Delete
void delete(Book... book);
//删除所有书籍信息
@Query("DELETE from Book")
void deleteAll();
@Update
int update(Book... book);
//加载所有书籍信息
@Query("SELECT * FROM Book")//表名建议和类名一致
List<Book> queryAll();
//根据名字加载书籍
@Query("SELECT * FROM Book WHERE name = :name ORDER BY id DESC limit 1")
Book queryByName(String name);
}
3.创建数据库类,添加@Database注解
//entities表示该数据库有哪些表,version表示数据库的版本号
//exportSchema表示是否导出数据库信息的json串,建议设为false,若设为true还需指定json
@Database(entities = {Book.class},version = 1,exportSchema = true)
public abstract class BookDatabase extends RoomDatabase {
public abstract BookDao bookDao();
@NonNull
@Override
protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration config) {
return null;
}
@NonNull
@Override
protected InvalidationTracker createInvalidationTracker() {
return null;
}
@Override
public void clearAllTables() {
}
}
exportSchema为true,添加json文件保存路径
javaCompileOptions {
annotationProcessorOptions {
//指定数据库schema导出的位置
arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
}
}
4.在Application类声明数据库的唯一实例
public class MyApplication extends Application {
private static MyApplication mApp;
//声明一个公共的信息映射对象,可当做全局变量使用
public HashMap<String,String> infoMap = new HashMap<>();
private BookDatabase bookDatabase;
public static MyApplication getInstance(){
return mApp;
}
@Override
public void onCreate() {
super.onCreate();
mApp = this;
Log.d("syf","onCreate.....");
//构建数据库的实例
bookDatabase = Room.databaseBuilder(this,BookDatabase.class,"book")
//允许迁移数据库(发生数据库变更时,Room默认删除原数据库再创建新数据库。如此一来原来的记录会丢失,故而要改为迁移方式以便保存原有记录)
.addMigrations()
.allowMainThreadQueries()//一般不允许在主线程操作数据库
.build();
}
@Override
public void onTerminate() {
super.onTerminate();
Log.d("syf","onTerminate.....");
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d("syf","onConfigurationChanged.....");
}
public BookDatabase getBookDB(){
return bookDatabase;
}
}
5.操作数据
public class RoomWriteActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_book_name;
private EditText et_editor;
private EditText et_publication;
private EditText et_money;
private BookDao bookDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_room_write);
et_book_name = findViewById(R.id.et_book_name);
et_editor = findViewById(R.id.et_editor);
et_publication = findViewById(R.id.et_publication);
et_money = findViewById(R.id.et_money);
findViewById(R.id.btn_add).setOnClickListener(this);
findViewById(R.id.btn_delete).setOnClickListener(this);
findViewById(R.id.btn_update).setOnClickListener(this);
findViewById(R.id.btn_query).setOnClickListener(this);
//从App实例中获取唯一的书籍持久化对象
bookDao = MyApplication.getInstance().getBookDB().bookDao();
}
@Override
public void onClick(View v) {
String name = et_book_name.getText().toString();
String editor = et_editor.getText().toString();
String publication = et_publication.getText().toString();
String money = et_money.getText().toString();
switch (v.getId()) {
case R.id.btn_add:
Book b1 = new Book();
b1.setName(name);
b1.setEditor(editor);
b1.setPublication(publication);
b1.setMoney(Double.parseDouble(money));
bookDao.insert(b1);
Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_delete:
Book b2 = new Book();
b2.setId(1);
bookDao.delete(b2);
break;
case R.id.btn_update:
Book b3 = new Book();
//根据名字查询到数据库中已有的记录
Book b4 = bookDao.queryByName(name);
b3.setId(b4.getId());
b3.setName(name);
b3.setEditor(editor);
b3.setPublication(publication);
b3.setMoney(Double.parseDouble(money));
bookDao.update(b3);
break;
case R.id.btn_query:
List<Book> list = bookDao.queryAll();
for (Book b : list) {
Log.d("syf", b.toString());
}
break;
}
}