专栏首页指点的专栏Android文件读写和使用SharedPreferences储存数据

Android文件读写和使用SharedPreferences储存数据

程序的终归目的还是操作数据来达到实现一些特定功能,在Android中,我们可以通过操作文件或者使用SharedPreferences还有数据库来保存一些数据。首先来看一下Android文件的读写:

假设我们现在有这么一个需求:一个Activity中有一个EditText,在每次这个程序启动的时候我们要恢复用户上一次在EditText中输入的数据。
Ok,轮到文件操作大展身手了:

新建一个Android工程: activity_main.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"
    android:gravity="center_horizontal"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

简单的布局,就不介绍了,接下来是MainActivity.java:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.widget.EditText;

public class MainActivity extends Activity {

    private FileOutputStream out = null;
    private BufferedWriter writer = null;
    private FileInputStream in = null;
    private BufferedReader reader = null;
    private EditText editText = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = (EditText) findViewById(R.id.editText);
        String str = readText();
        editText.setText(str);
        editText.setSelection(str.length());    // 光标移至末尾继续输入
    }

    private String readText()
    {
        StringBuilder readString = new StringBuilder();
        try
        {
            String line = null;
            in = openFileInput("dataSave");
            reader = new BufferedReader(new InputStreamReader(in));
            while((line = reader.readLine()) != null)
            {
                readString.append(line);
            }
            if(reader != null)
            {
                reader.close();
            }
        }catch (IOException e)
        {
            e.printStackTrace();
        }
        String str = readString.toString();
        if(!TextUtils.isEmpty(str)) // 如果字符串不空,返回这个字符串
        {
            return str;
        }
        else 
        {
            return null;
        }
    }

    private void saveText()
    {
        String saveString = null;
        saveString = editText.getText().toString();
        try {
            out = openFileOutput("dataSave", Context.MODE_PRIVATE); 
            /*
            * 第一个参数是文件名,第二个是操作模式,目前只有两种
            * 操作模式:MODE_PRIVATE(创建的文件名已经存在时替
            * 换该文件),
            * MODE_APPEND(创建的文件名已经存在时像该文件件
            * 末尾添加数据)
            */
            writer = new BufferedWriter(new OutputStreamWriter(out));
            writer.write(saveString);
            if(writer != null)
            {
                writer.close();
            }
        } catch (IOException e){
            e.printStackTrace();
        } 
    }

    @Override 
    public void onDestroy()
    {
        super.onDestroy();
        saveText();
    }
}

在 MainActivity.java 文件中,我们定义了两个方法:saveText() 和 readText() 分别用于储存 EditText 中输入的内容和恢复 EditText 中的内容。主要是一些Java中的文件操作,如果不熟悉的话可以去网上找一些教程。在 onDestroy 方法中调用 saveText 来储存 EditText 中的数据。,在 onCreate 方法中我们进行恢复 EditText 中的数据。这里说一些 TextUtils.isEmpty(CharSequence str) 方法,一个静态方法,如果str为null或者为空字符,这个方法都会返回true。这里用来检测字符串是否为空。运行程序:

刚开始什么都没有(如果你是第一次运行这个程序) 输入字符:

退出程序之后再次进入程序:

成功恢复!

前面介绍的文件操作储存数据是用文本文件或者二进制文件来储存数据的,下面介绍一个新的数据储存方式:SharedPreferences

SharedPreferences 储存的文件采用xml格式的文件来储存数据,通过“键--值“对的方式来储存,读取的时候通过“键”来读取对应的“值”。

SharedPreferences现在只有一种MODE_PRIVATE(和上面介绍的一样)操作模式。用SharedPreferences储存的文件放在 /data/data/<package name>/shared-prefs/ 目录下的,
pack name为应用程序的包名

我们有三种方式来获取SharedPreferences对象:
1、Context类的getSharedPreferences方法,此方法接收两个参数:SharedPreferences储存的文件名和操作模式。
2、Activity类中的getPreferences方法,此方法接受一个参数:操作模式(MODE_PRIVATE),储存的文件名为当前Activity对象的类名
3、PreferenceManager类中的静态方法:getDefaultSharedPreferences,此方法接收一个Context类型的参数。

得到了SharedPreferences对象之后我们就可以利用它进行数据的储存了:
(1) 调用Sharedpreferences 对象的 edit() 方法获取一个SharedPreferences.Editor 对象
(2) 使用SharedPreferences.Editor 对象的特性方法储存数据(putString()...)
(3) 调用SharedPreferences.Editor 对象的apply() 方法提交数据,完成储存。

下面通过一个简单的实例来介绍SharedPreferences:模拟账号登录过程中的记住密码问题: 新建一个Android工程: activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TableRow 
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#00FFFF"
            android:text="用户名"/>
        <EditText 
            android:id="@+id/userNameEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="输入用户名"/>
    </TableRow>
    <TableRow 
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#FF00FF"
            android:text="  密码  "/>
        <EditText 
            android:id="@+id/passwordEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:password="true"
            android:layout_weight="1"
            android:hint="输入密码"/>
    </TableRow>
    <CheckBox 
        android:id="@+id/savePasswordsCheckBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="记住密码"
        android:checked="false" />
    <TableRow 
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
        <Button 
            android:id="@+id/registerButton"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="注册"
            android:background="#FFAAFF"/>
        <Button 
            android:id="@+id/loginButton"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#AADDFF"
            android:text="登录"/>
    </TableRow>

</TableLayout>

布局文件采用TableLayout布局方式,TableLayout很适合设计账号登录界面,主要的布局逻辑并不难,一行账号输入,一行密码输入,一行单选框,用于判断是否记住密码,还有一行就是登录和注册按钮。 MainActivity.java:

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;

public class MainActivity extends Activity {

    private Button button = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login_activity);

        loadUserInfo();
        button = (Button) findViewById(R.id.loginButton);
        button.setOnClickListener(listener);

    }

    private View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch(v.getId())
            {
            case R.id.loginButton:
                login();
                break;
            }
        }
    };

    @SuppressLint("NewApi")
    private void login() // 单击登录按钮事件
    {
        CheckBox checkBox = (CheckBox) findViewById(R.id.savePasswordsCheckBox);

        SharedPreferences.Editor editor = getSharedPreferences("userInfo", Context.MODE_PRIVATE).edit();// 获取 Sharedpreferences.Editor 对象
        editor.putString("userName", ((EditText) findViewById(R.id.userNameEditText)).getText().toString());
        if(checkBox.isChecked()) 
        {
            editor.putString("passwords", ((EditText) findViewById(R.id.passwordEditText)).getText().toString()); // 如果选中记住密码单选框就储存密码
        }
        editor.apply(); // 上传数据
        Toast.makeText(this, "单击登录按钮", Toast.LENGTH_SHORT).show();
    }

    private void loadUserInfo()
    {
        SharedPreferences preferences = getSharedPreferences("userInfo", Context.MODE_PRIVATE);
        String userName = preferences.getString("userName", ""); // 第一个参数是“键”,第二个参数是如果数据不存在默认的返回数据
        String passwords = preferences.getString("passwords", "");
        ((EditText) findViewById(R.id.userNameEditText)).setText(userName);
        ((EditText) findViewById(R.id.passwordEditText)).setText(passwords);
        if(!TextUtils.isEmpty(passwords))
        {
            ((CheckBox) findViewById(R.id.savePasswordsCheckBox)).setChecked(true); // 更新单选框的状态
        }
    }
}

主要的思想还是通过两个自定义方法实现:login() 方法用于单击“登录”按钮时对用户名和密码等信息的储存,loadUserInfo() 方法用于恢复用户名和密码等操作。Ok,忙了这么久,让我们来试试:

如果你是第一次运行程序,那么你的界面应该是这样的。输入账户和密码,单击记住密码:

点击登录按钮。然后完全退出程序,再次启动程序:

Yes,成功记住了密码,我们可以在模拟器的文件管理中找到我们刚刚储存的文件

也可以将其导出到电脑中查看

当然,这里的代码还有很多不足之处,比如没有实现用户名和密码检测,没有对空的用户名和密码进行处理,有兴趣的小伙伴们可以自己实现。 如果博客中有什么不正确的地方,还请多多指点。 谢谢观看。。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android中的权限问题

    在Android程序中,在执行形如访问网络、读取联系人时都要声明权限,在 Android 系统版本小于6.0时,所有的权限只需要在AndroidManifest...

    指点
  • Android 中 View 的滑动

    Android View控件的滑动是 Android 的一个重要内容。在 View 需要变换位置时,为其添加适当的滑动效果,获得更好的用户体验,下面来看一下怎样...

    指点
  • Android自定义View

    前几天在郭霖大神的博客上看了自定义View的知识,感觉受益良多,大神毕竟大神。在此总结一下关于Android 自定义View的用法:

    指点
  • Android开发之漫漫长途 番外篇——自定义View的各种姿势1

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索...

    mafeibiao
  • Android数据读取之Sqlite数据库操作

    咱们书接上文,继续来说说Android数据读取,这回,我们要讲的是Sqlite数据库的相关操作。以一个实例开始吧:

    lzugis
  • 安卓开发_数据存储技术_内部存储

    听着music睡
  • 2-VVI-材料设计之TabLayout下标签

    张风捷特烈
  • 动画必须有(二):悬浮菜单了解一下!

    SeanDepp
  • [android] 练习viewpagerindicator的使用(一)

    陶士涵
  • 用 CoordinatorLayout 处理滚动

    Android 开发者

扫码关注云+社区

领取腾讯云代金券