Android游戏开发中常用的保存数据的方式有四种,分别是SharedPreference、文件存储、SQLite和ContentProvider。下面先作简单的介绍。
1、SharedPreference
此保存方式试用于简单数据的保存,文如其名属于配置性质的保存,不适合数据比较大的保存方式。
2、文件存储(FIleInputStream/FileOutputStream)
此保存方式比较适合游戏的保存和使用,可以保存较大的数据,因为相对于SQLite来说更容易让童鞋们接受,此方式不仅能把数据存储在系统中也能将数据保存到SDcard中。
3、SQLite
此保存方式比较适合游戏的保存和使用,可以保存较大的数据,并且可以将自己的数据存储到文件系统或者数据库当中,也可以将自己的数据存储到SQLite数据库当中,也能将数据保存到SDcard中。
4、ContentProvider(不推荐用于戏保存)
此保存方式不推荐用于游戏保存,因为此方式不仅能存储较大数据,还支持多个程序之间就的数据进行交换!但是由于游戏中基本就不可能去访问外部应用的数据,所以对于此方式我不予讲解, 有兴趣的可以自己找资料 学习。
以上对几种常用的保存方式进行了概述,下面分别讲解每种方式的优缺点、如何实现和需要注意的问题。
1、保存方式之SharedPreference
优点: 简单、方便、适合简单数据的快速保存。
缺点:
1)存数的文件只能在同一包内使用,不能在不同包之间使用!
2)默认将数据存放在系统路径下 /data/data/com.himi/ ,没有找到放SD卡上的方法。
总结:其实本保存方式如同它的名字一样是个配置保存,虽然方便,但只适合存储比较简单的数据!
main.xml :
XML/HTML代码
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <TextView android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:text="保存数据练习!"
- android:textSize="20sp" android:textColor="#ff0000" android:id="@+id/tv_title" />
- <TextView android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:text="请输入帐号" />
- <EditText android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:id="@+id/editText_Login"
- android:text=""></EditText>
- <TextView android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:text="请输入密码" />
- <EditText android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:id="@+id/editText_Password"
- android:text=""></EditText>
- <Button android:id="@+id/button_save" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:text="保存"></Button>
- <Button android:id="@+id/button_load" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:text="取出数据"
- android:visibility="invisible"></Button>
- </LinearLayout>
先把xml文件放上来的原因是因为我在此篇中介绍的 SharedPreference 和 文件存储 (FIleInputStream/FileOutputStream),都共用此xml,很简单,两个textview 两个 editview 以及两个button,这里就不多说了。
下面是SharedPreference 的代码实现和详细讲解:
Java代码
-
-
-
-
-
-
-
-
-
- public class MainActivity extends Activity implements OnClickListener {
- private EditText et_login, et_password;
- private Button btn_save;
- private TextView tv_title;
- private SharedPreferences sp;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- this.requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.main);
- btn_save = (Button) findViewById(R.id.button_save);
- btn_save.setOnClickListener(this);
- et_login = (EditText) findViewById(R.id.editText_Login);
- et_password = (EditText) findViewById(R.id.editText_Password);
- tv_title = (TextView) findViewById(R.id.tv_title);
-
-
- sp = getSharedPreferences("Setting_himi", MODE_PRIVATE);
-
-
-
-
-
- sp.getString("login", "");
-
-
- et_login.setText(sp.getString("login", ""));
- et_password.setText(sp.getString("password", ""));
- }
- @Override
- public void onClick(View v) {
- if (v == btn_save) {
- if (et_login.getText().toString().equals(""))
- tv_title.setText("请输入帐号!");
- else if (et_password.getText().toString().equals(""))
- tv_title.setText("请输入密码!");
- else {
- sp.edit()
- .putString("login", et_login.getText().toString())
- .putString("password", et_password.getText().toString())
- .commit();
-
- tv_title.setText("保存成功!可重新打开此程序,测试是否已经保存数据!" +
- "/n(或者在'File Explorer'窗口下-data-data-com.himi路径下" +
- "是否存在" +"了'Setting_himi.xml')");
- }
- }
- }
- }
代码中的注释的很清楚了,比较简单,不多说了。
2、保存方式之:文件存储 OutputStream/InputStream
优点:
1)适合游戏存储,能存储较大数据;
2)不仅能存储到系统中,也能存储到SD卡中!
总结:如果童鞋们对SQL不太熟习的话那么选择此种方式最为合适的啦。
以上代码中实现了两种流形式来完成写入和读入,这里我们为什么要使用Data流来包装,其实不光是获得更多的操作方式,最主要的是方便快捷,你比如用file来读入的时候,明显的复杂了一些不说,它还一次性把所有数据都取出来了,不便于对数据的处理!
强调的有几点:
1、在一开始对数据的访问再次提醒童鞋们,这个跟sharedPreference的获取方式不一样,sharedPreference 的获取方式可以得到一个默认的值,但是你用咱们获取的是个文件 而且直接就去open这个文件,一旦不存在必定异常,所以这一块的异常处理,以及finally的处理一定要处理得当。
2、其实在一开始用data包装的时候发现写入的字符串在读入的时候发现字符乱码了,查了api才发现,api规定当写入字符串的时候必须写入UTF-8格式的编码,但是后来不知道怎么了就没事了。所以这里如果童鞋们遇到此问题,我给出大家一个解决方法,就是在写入的时候我们不要去DataOutputStream 来包装而是用,OutputStreamWriter ,因为在构造的可以设定编码!
OutputStreamWriter osw = new OutputStreamWriter(fis,”UTF-8″);
String content = EncodingUtils.getString(buffer, ”UTF-8″); 这个也能把字符数组转码制!
这样写入的就肯定是UTF-8编码的字符啦。
下面介绍如何把我们的数据通过 OutputStream/InputStream 存入SD卡中!
其实将我们的数据放入SD卡中,无疑就需要对代码进行两处的修改:
注意:一定要有SD卡!对于如何创建SD卡在前面文章中已经说了两种方式,不会的童鞋可以去看下。
第一:检查是否装有SD卡;
第二:修改读入的地方(备注1)。
fis = this.openFileInput(“save.himi”); //这里没有路径,路径是默认的 data-data-com.himi-files下
替换成我们的SD卡的路径就可以了:
File path = new File(“/sdcard/himi/save.himi”);//这里新建一个File目录路径
fis = new FileInputStream(path);传入路径
第三:修改写入的地方(备注2)。
fos = this.openFileOutput(“save.himi”, MODE_PRIVATE);这里也是默认路径,需要对其修改。
注意:这里修改了,那么在finally中的判定大家也要对应的适当修改;
注意:如果是系统路径,当没有此文件的时候,android 会默认创建一个!但是我们放入SD卡的时候要自己创建目录路径和文件!
Java代码
- if (Environment.getExternalStorageState() != null) {
- Log.v("Himi", "有SD卡");
- File path = new File("/sdcard/himi");
- File f = new File("/sdcard/himi/save.himi");
- if (!path.exists()) {
- path.mkdirs();
- }
- if (!f.exists()) {
- f.createNewFile();
- }
- fos = new FileOutputStream(f);
- }
第四:因为我们要在SD卡中进行写入的操作,所以要在配置文件中声明权限!
XML/HTML代码
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.himi"
- android:versionCode="1"
- android:versionName="1.0">
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".MainActivity"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-sdk android:minSdkVersion="4" />
- </manifest>
这一句就是啦~
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
为了让大家看到所放的位置,所以把整个xml放出来供参考。
那么当创建路径和文件的时候,我们对其检查SD卡中是否已经存在exists()方法 ,如果已经存在就不去创建,这样避免下次再次写入数据的时候又新建了文件和路径。
其实我们在可以在启动程序的时候判断如果没有此文件,我们可以直接紧接着创建一个文件,这些都属于优化上的了,我主要是让大家引入,学会,那么其他的简化啦,优化啦,其他方式去实现啦都留给各位同学自己了。
本文效果图:
OK、今天就先介绍到这里,后面会单独剖析SQLite如何存入数据,以及对数据操作的! 希望大家继续关注!