zoukankan      html  css  js  c++  java
  • 【读书笔记《Android游戏编程之从零开始》】20.游戏开发基础(游戏数据存储)

    对于数据的存储,Android 提供了4种保存方式。

    (1)SharedPreference

    此方法适用于简单数据的保持,文如其名,属于配置性质的保存,不适合比较大的情况,默认存放在手机内存里

    (2)FileInputStream/FileOutputStream

    此方式比较适合游戏的保存和使用,流文件数据存储可以保持较大的数据,而且通过此方式不仅能把数据存储在手机内存中,也能将数据保存到手机额SDcard中。

    (3)SQLite

    此方式也适合游戏的保存和使用,不仅可以保存较大的数据,而且可以将自己的数据存储到文件系统或者数据库当中,如SQLite数据库,也能将数据保存到SDcard 中。

    (4)ContentProvider

    此方式不推荐用于游戏保存,虽然此方式能存储较大数据,还支持多个程序之间的数据进行交换,但游戏中基本就不可能去访问外部应用程序的数据。

     

    1.SharedPreference

    SharedPreference 实例是通过Context 对象得到的:

    Context.getSharePreference(String name,int mode)

    作用:利用Context 对象获取一个SharedPreference 实例

    参数1:生成保持记录的文件名

    参数2:操作模式

     

    SharedPreference 实例的操作模式一共有四种:

    Context.MODE_PRIVATE:新内容覆盖原内容。

    Context.MODE_APPEND:新内容追加到原内容后。

    Context.MODE_WORLD_READABLE:允许其他应用程序读取。

    Context.MODE_WORLD_WRITEABLE:允许其他应用程序写入,会覆盖原数据。

     

    SharedPreference 常用函数:

    getFloat(String key,float defValue)

    getInt(String key,int defValue)

    getLong(String key,long defValue)

    getString(String key,String defValue)

    getBoolean(String key,boolean defValue)

     

    SharedPreference 常用函数的作用是获取存储文件中的值,根据方法不同获取不同对应的类型值,一般第一个参数为索引Key值,第二个参数为在存储文件中找不到对应 value 值时,默认的返回值。

     

    对应的,在对存储文件的数据进行存入操作时,首先需要利用 SharedPreference 实例得到一个编辑对象:

    SharedPreference.Editor edit;

    得到编辑对象后就可以对 SharedPreference 中的数据进行操作。

    SharedPreference.Editor.putFloat(arg0,arg1)

    SharedPreference.Editor.putInt(arg0,arg1)

    SharedPreference.Editor.putLong(arg0,arg1)

    SharedPreference.Editor.putString(arg0,arg1)

    SharedPreference.Editor.putBoolean(arg0,arg1)

    以上方法的作用是对存储的数据进行操作(写入、保存),其中第一个参数是需要保存数据额Key值索引,第二个参数是需要保存的数据。

    到此进行了保存和修改,还需要将其编辑的数据进行提交方可完成存入和修改:

    SharedPreference.Editor.commit()

    如果想删除存储文件中的一条数据,可以使用以下函数:

    SharedPreference.Editor.clear()

     

    下面用一个简单小游戏进行说明,先看下效果图:

     

     新建项目,游戏框架为 SurfaceView 游戏框架,修改 MySurfaceView 类如下:

    import android.content.Context;
    import android.content.SharedPreferences;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.view.KeyEvent;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.SurfaceHolder.Callback;
    
    
    public class MySurfaceView extends SurfaceView implements Callback, Runnable {
        private SurfaceHolder sfh;
        private Paint paint;
        private Thread th;
        private boolean flag;
        private Canvas canvas;
        private int screenW, screenH;
        //记录当前圆形所在九宫格的位置下标
        private int creentTileIndex;
        //声明一个SharedPreferences对象
        private SharedPreferences sp;
    
        /**
         * SurfaceView初始化函数
         */
        public MySurfaceView(Context context) {
            super(context);
            sfh = this.getHolder();
            sfh.addCallback(this);
            paint = new Paint();
            paint.setColor(Color.BLACK);
            paint.setAntiAlias(true);
            setFocusable(true);
            //通过Context获取SharedPreference实例
            sp = context.getSharedPreferences("SaveName", Context.MODE_PRIVATE);
            //每次程序运行时获取圆形的下标
            int tempIndex = sp.getInt("CirCleIndex", -1);
            //判定如果返回-1 说明没有找到,就不对当前记录圆形的变量进行赋值
            if (tempIndex != -1) {
                creentTileIndex = tempIndex;
            }
        }
    
        /**
         * SurfaceView视图创建,响应此函数
         */
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            screenW = this.getWidth();
            screenH = this.getHeight();
            flag = true;
            //实例线程
            th = new Thread(this);
            //启动线程
            th.start();
        }
    
        /**
         * 游戏绘图
         */
        public void myDraw() {
            try {
                canvas = sfh.lockCanvas();
                if (canvas != null) {
                    canvas.drawColor(Color.WHITE);
                    paint.setColor(Color.BLACK);
                    paint.setStyle(Style.STROKE);
                    //绘制九宫格(将屏幕九等份)
                    //得到每个方格的宽高
                    int tileW = screenW / 3;
                    int tileH = screenH / 3;
                    for (int i = 0; i < 3; i++) {
                        for (int j = 0; j < 3; j++) {
                            canvas.drawRect(i * tileW, j * tileH, (i + 1) * tileW, (j + 1) * tileH, paint);
                        }
                    }
                    //根据得到的圆形下标位置进行绘制相应的方格中
                    paint.setStyle(Style.FILL);
                    canvas.drawCircle(creentTileIndex % 3 * tileW + tileW / 2, creentTileIndex / 3 * tileH + tileH / 2, 30, paint);
                    //操作说明
                    canvas.drawText("上键:保存游戏", 0, 20, paint);
                    canvas.drawText("下键:读取游戏", 110, 20, paint);
                    canvas.drawText("左右键:移动圆形", 215, 20, paint);
                }
            } catch (Exception e) {
                // TODO: handle exception
            } finally {
                if (canvas != null)
                    sfh.unlockCanvasAndPost(canvas);
            }
        }
    
        /**
         * 触屏事件监听
         */
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return true;
        }
    
        /**
         * 按键事件监听
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            //上键保存游戏状态
            if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                sp.edit().putInt("CirCleIndex", creentTileIndex).commit();
                //下键读取游戏状态
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                int tempIndex = sp.getInt("CirCleIndex", -1);
                if (tempIndex != -1) {
                    creentTileIndex = tempIndex;
                }
                //圆形的移动
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                if (creentTileIndex > 0) {
                    creentTileIndex -= 1;
                }
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                if (creentTileIndex < 8) {
                    creentTileIndex += 1;
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
        /**
         * 游戏逻辑
         */
        private void logic() {
        }
    
        @Override
        public void run() {
            while (flag) {
                long start = System.currentTimeMillis();
                myDraw();
                logic();
                long end = System.currentTimeMillis();
                try {
                    if (end - start < 50) {
                        Thread.sleep(50 - (end - start));
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * SurfaceView视图状态发生改变,响应此函数
         */
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }
    
        /**
         * SurfaceView视图消亡时,响应此函数
         */
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            flag = false;
        }
    }
    View Code

    2.流文件存储

    利用前面 SharedPreference 的例子,去除 SharedPreference 存储部分,改用流文件形式进行保存,只需要修改其中“保存”和“读取”操作,也就是修改“按键事件”:

        /**
         * 按键事件监听
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            // 用到的读出、写入流
            FileOutputStream fos = null;
            FileInputStream fis = null;
            DataOutputStream dos = null;
            DataInputStream dis = null;
            // 上键保存游戏状态
            if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                try {
                    // 利用Activity 实例打开流文件得到一个写入流
                    fos = MainActivity.instance.openFileOutput("save.yc",
                            Context.MODE_PRIVATE);
                    // 将写入流封装在数据写入流中
                    dos = new DataOutputStream(fos);
                    //写入一个int 类型(将圆形所在格子的下表写入流文件中)
                    dos.writeInt(creentTileIndex);
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }finally{
                    //即使保存时发生异常也要关闭流
                    try {
                        if(fos!=null) fos.close();
                        if(dos!=null)dos.close();
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                }
                // 下键读取游戏状态
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                try {
                    if(MainActivity.instance.openFileInput("save.yc")!=null)
                    {
                        try {
                            //利用Activity 实例打开流文件得到一个读出流
                            fis = MainActivity.instance.openFileInput("save.yc");
                            //将读出流封装在数据读入流中
                            dis = new DataInputStream(fis);
                            //读出一个int 类型赋值与圆形所在格子的下标
                            creentTileIndex =dis.readInt();
                        } catch (Exception e) {
                            // TODO: handle exception
                        }finally{
                            if(fis!=null)fis.close();
                            if(dis!=null)dis.close();
                        }
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
                // 圆形的移动
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                if (creentTileIndex > 0) {
                    creentTileIndex -= 1;
                }
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                if (creentTileIndex < 8) {
                    creentTileIndex += 1;
                }
            }
            return super.onKeyDown(keyCode, event);
        }

    不管是读入还是写入,都是通过Activity 打开流文件得到输入输出流。当需要写入流文件时,如果打开的流文件不存在,那么Android 会自动生成对应的流文件;而当需要读入流文件时,首先应判断流文件是否存在,一旦流文件不存在,就会抛出异常。

    这里的流形式的保存操作比较简单,需要注意的是:

    ● 读流时,一定要记得判断是否存在需要操作的流文件;

    ● 写入和读入的数据类型要配对,顺序也不能错;例如:写入时,先写入了一个 Int值,然后又写入了一个String 值;那么读入时,也应该先读 Int 类型,然后再读 String 类型;

    ● 流一旦打开一定要关闭,为了避免流操作出现异常,需确保正常关闭流,应该将关闭操作写在finally 语句中;

    ● file 流使用 Data 流进行了封装,这样做的原因是可以获得更多的操作方式,便于对数据的处理。

    以上是使用流文件的保存方式,但是也只是将保存后的流文件默认放在了系统内存里。一般游戏的数据可能会有很多,所以不应该放在手机内存中,而是放在 SDCard 中,这样就不要担心系统因游戏保存的数据过多导致内存不足等问题。

    将流文件保存在 SDCard 中的详细步骤如下:

    (1)声明读取权限:

    Android 中的一些操作,比如:读取通讯录信息、发送信息、使用联网、GPRS等功能都需要在项目 AndroidManifest.xml 中声明使用权限,然后才可以正常使用其功能。

    当然在很多时候,是不知道是否需要声明添加权限的,其实这个也不用知道,因为如果用到这些需要声明权限的功能,且恰好没有声明的情况下,在LogCat 中是会报异常的,其异常则提醒需要添加对应的权限。

    写入权限如下:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    (2)创建目录和存储文件

     使用 SDCard 的方式进行存储数据,写入的时候 Android 不会跟存储系统默认路径那样默认生成存储文件,所以必须自己来创建;如果存储的文件有自定义路径的话,那么这个路径也需要手动添加。

    假定存储文件在 SDCard 的路径为 /sdcard/yc/save.yc 。

    ① 首先需要创建路径 /sdcard/yc

    File path = new File(" /sdcard/yc");// 创建目录  
    if(!path.exists())// 目录存在返回true
    {
      path.mkdirs();// 创建一个目录                      
    }

    boolean File.exists()

     作用:判断是否存在当前目录

    返回值:当前目录存在返回true

    boolean File.mkdirs()

    作用:创建一个目录

    返回值:当创建成功返回true

    ②然后创建存储文件:/sdcard/yc/save.yc

    File path_File = new File(" /sdcard/yc/save.yc");// 创建文件  
    if(!path_File.exists())// 文件存在返回true
    {
       path_File.createNewFile();// 创建一个文件                      
    }

    boolean File.createNewFile()

    作用:创建一个文件

    返回值:创建成功返回true

    (3)通过加载指定路径的存储文件获取输入输出流

    ● 输入流:FileInputStream fis = new FileInputStream(File file);

    ● 输出流:FileOutputStream fos = new FileOutputStream(File file);

    除此之外还需要知道一点,因为有时手机并没有安装 SDCard ,或者当前SDCard 处于被移除的状态时,为了避免这两种情况带来的异常,需要通过下面方法获取当前手机设备SDCard 的状态:

    String Environment.getExternalStorageStorageState()

    作用:获取当前SDCard的状态

    返回值:当前 SDCard 不存在时,返回null ;当 SDCard 处于移除状态时,返回“removed”;

    所以当默认手机设备存在 SDCard 时,保存在 SDCard 中 ;当 SDCard 不存在或者正处于被移除的状态时,默认将数据保存在手机内存中。上面的“按键事件”修改如下:

        /**
         * 按键事件监听
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            //用到的读出、写入流
            FileOutputStream fos = null;
            FileInputStream fis = null;
            DataOutputStream dos = null;
            DataInputStream dis = null;
            //上键保存游戏状态
            if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                try {
                    // 从SDcard中写入数据
                    // 试探终端是否有sdcard! 并且探测SDCard是否处于被移除的状态
                    if (Environment.getExternalStorageState() != null && !Environment.getExternalStorageState().equals("removed")) {
                        Log.v("yc", "写入,有SD卡");
                        File path = new File("/sdcard/yc");// 创建目录  
                        File f = new File("/sdcard/yc/save.yc");// 创建文件  
                        if (!path.exists()) {// 目录存在返回true  
                            path.mkdirs();// 创建一个目录  
                        }
                        if (!f.exists()) {// 文件存在返回true  
                            f.createNewFile();// 创建一个文件  
                        }
                        fos = new FileOutputStream(f);// 将数据存入sd卡中  
                    } else {
                        //默认系统路径
                        //利用Activity实例打开流文件得到一个写入流
                        fos = MainActivity.instance.openFileOutput("save.yc", Context.MODE_PRIVATE);
                    }
                    //将写入流封装在数据写入流中
                    dos = new DataOutputStream(fos);
                    //写入一个int类型(将圆形所在格子的下标写入流文件中)
                    dos.writeInt(creentTileIndex);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    //即使保存时发生异常,也要关闭流
                    try {
                        if (fos != null)
                            fos.close();
                        if (dos != null)
                            dos.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                //下键读取游戏状态
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                boolean isHaveSDCard = false;
                // 从SDcard中读取数据
                // 试探终端是否有sdcard! 并且探测SDCard是否处于被移除的状态
                if (Environment.getExternalStorageState() != null && !Environment.getExternalStorageState().equals("removed")) { 
                    Log.v("yc", "读取,有SD卡");
                    isHaveSDCard = true;
                }
                try {
                    if (isHaveSDCard) {
                        File path = new File("/sdcard/yc");// 创建目录  
                        File f = new File("/sdcard/yc/save.yc");// 创建文件  
                        if (!path.exists()) {// 目录存在返回true
                            return false;
                        } else {
                            if (!f.exists()) {// 文件存在返回true  
                                return false;
                            }
                        }
                        fis = new FileInputStream(f);// 将数据存入sd卡中  
                    } else {
                        if (MainActivity.instance.openFileInput("save.yc") != null) {
                            //利用Activity实例打开流文件得到一个读入流
                            fis = MainActivity.instance.openFileInput("save.yc");
                        }
                    }
                    //将读入流封装在数据读入流中
                    dis = new DataInputStream(fis);
                    //读出一个Int类型赋值与圆形所在格子的下标
                    creentTileIndex = dis.readInt();
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    //即使读取时发生异常,也要关闭流
                    try {
                        if (fis != null)
                            fis.close();
                        if (dis != null)
                            dis.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                if (creentTileIndex > 0) {
                    creentTileIndex -= 1;
                }
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                if (creentTileIndex < 8) {
                    creentTileIndex += 1;
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    View Code

    3.SQLite 轻量级数据库

    此方式也适合游戏的保存和使用,不仅可以保存较大的数据,而且可以将自己的数据存储到文件系统或者数据库当中,如SQLite数据库,也能将数据保存到SDcard 中。

    SQLite是一款轻量级数据库,它的设计目的是嵌入式,而且它占用的资源非常少,在嵌入式设备中,只需要几百KB!

    SQLite的特性:
    轻量级:使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小。
    独立性:SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的“安装”。
    隔离性:SQLite 数据库中所有的信息(比如表、视图、触发器等)都包含在一个文件夹内,方便管理和维护。
    跨平台:SQLite 目前支持大部分操作系统,不至电脑操作系统更在众多的手机系统也是能够运行,比如:Android。
    多语言接口:SQLite 数据库支持多语言编程接口。
    安全性:SQLite 数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只能有一个可以写入数据.

    优点:1.能存储较多的数据。2.能将数据库文件存放到SD卡中!


    什么是 SQLiteDatabase?

         一个 SQLiteDatabase 的实例代表了一个SQLite 的数据库,通过SQLiteDatabase 实例的一些方法,我们可以执行SQL 语句,对数        据库进行增、删、查、改的操作。需要注意的是,数据库对于一个应用来说是私有的,并且在一个应用当中,数据库的名字也是惟一的。

     
    什么是 SQLiteOpenHelper ?

         根据这名字,我们可以看出这个类是一个辅助类。这个类主要生成一个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法getWritableDatabase(),或者getReadableDatabase()方法的时候,如果当时没有数据,那么Android 系统就会自动生成一个数据库。SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里边的3 个函数

    什么是 ContentValues 类?

         ContentValues 类和Hashmap/Hashtable 比较类似,它也是负责存储一些名值对,但是它存储的名值对当中的名是一个String 类型,而值都是基本类型。
     
    什么是 Cursor ?

         Cursor 在Android 当中是一个非常有用的接口,通过Cursor 我们可以对从数据库查询出来的结果集进行随机的读写访问。

    同样利用前面 SharedPreference 的例子,去除 SharedPreference 存储部分,改用SQLite进行保存。

    ① 首先新建一个类MySQLiteOpenHelper继承SQLiteOpenHelper;写一个构造,重写两个函数:

    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.util.Log;
    
    public class MySQLiteOpenHelper extends SQLiteOpenHelper {
        public final static int VERSION = 1;// 版本号
        public final static String TABLE_NAME = "INDEXINFO";// 表名
        public final static String Param1 = "ID";// 后面ContentProvider使用
        public final static String Param2 = "TITLEINDEX";
        public final static String DATABASE_NAME = "yc.db";
    
        public MySQLiteOpenHelper(Context context) {
            // 在Android 中创建和打开一个数据库都可以使用openOrCreateDatabase 方法来实现,
            // 因为它会自动去检测是否存在这个数据库,如果存在则打开,不过不存在则创建一个数据库;
            // 创建成功则返回一个 SQLiteDatabase对象,否则抛出异常FileNotFoundException。
            // 下面是来创建一个名为"DATABASE_NAME"的数据库,并返回一个SQLiteDatabase对象
            super(context, DATABASE_NAME, null, VERSION);
        }
    
        /**
         * 在数据库第一次生成的时候会调用这个方法,一般我们在这个方法里边生成数据库表;
         */
        @Override
        public void onCreate(SQLiteDatabase db) {
            // SQL语句,这里是创建一个表明为yc的表,有2个参数ID和TITLEINDEX,其中ID为主键,自增。具体说明如下:
            // CREATE TABLE 创建一张表 然后后面是表名
            // 然后表的列,第一个是id 方便操作数据,int类型
            // PRIMARY KEY 是指主键 这是一个int型,用于唯一的标识一行;
            // AUTOINCREMENT 表示数据库会为每条记录的key加一,确保记录的唯一性;
            // 最后加入一列文本 int类型参数TITLEINDEX
    
            String str_sql = "CREATE TABLE " + TABLE_NAME + "(" + Param1
                    + " INTEGER PRIMARY KEY AUTOINCREMENT," + Param2
                    + "  INTEGER );";
            // execSQL()方法是执行一句sql语句
            db.execSQL(str_sql);
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // 一般默认情况下,当我们插入 数据库就立即更新
            // 当数据库需要升级的时候,Android 系统会主动的调用这个方法。
            // 一般我们在这个方法里边删除数据表,并建立新的数据表,
            // 当然是否还需要做其他的操作,完全取决于游戏需求。
            Log.v("y_Hint", "onUpgrade");
        }
    
    }
    View Code

    ② 在MySurfaceView类中创建对应的实例

    private MySQLiteOpenHelper myOpenHelper;// 创建一个继承SQLiteOpenHelper类实例
    private SQLiteDatabase db;

    ③ 在SurfaceView初始化函数中实例一个数据库辅助器

    // 实例一个数据库辅助器
    myOpenHelper = new MySQLiteOpenHelper(MainActivity.instance);

    ④ 最后修改按键监听事件,其实只需要修改其中“保存”和“读取”操作,代码如下:

        /**
         * 按键事件监听
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            db = myOpenHelper.getWritableDatabase(); // 实例数据库
            // 上键保存游戏状态
            if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                // ---------------------- SQL语句删除--------------
                String DELETE_DATA = "DELETE FROM " + MySQLiteOpenHelper.TABLE_NAME;
                db.execSQL(DELETE_DATA);
                
                // ---------------------- SQL语句插入--------------
                String INSERT_DATA = "INSERT INTO " + MySQLiteOpenHelper.TABLE_NAME
                        + "(" + MySQLiteOpenHelper.Param2 + ") values ("
                        + creentTileIndex + ")";
                db.execSQL(INSERT_DATA);
                // 下键读取游戏状态
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                // 数据查询
                Cursor cur = db.rawQuery("SELECT * FROM "
                        + MySQLiteOpenHelper.TABLE_NAME, null);
                if (cur != null) {
                    cur.moveToNext();
                    creentTileIndex = cur.getInt(1);
                }
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                if (creentTileIndex > 0) {
                    creentTileIndex -= 1;
                }
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                if (creentTileIndex < 8) {
                    creentTileIndex += 1;
                }
            }
            return super.onKeyDown(keyCode, event);
        }

    说明:

    在Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下:

     以下是方法和说明:

     move    以当前的位置为参考,将Cursor移动到指定的位置,成功返回true, 失败返回false

     moveToPosition 将Cursor移动到指定的位置,成功返回true,失败返回false

     moveToNext  将Cursor向前移动一个位置,成功返回true,失败返回false

     moveToLast    将Cursor向后移动一个位置,成功返回true,失败返回 false。

     movetoFirst  将Cursor移动到第一行,成功返回true,失败返回false

     isBeforeFirst     返回Cursor是否指向第一项数据之前

     isAfterLast  返回Cursor是否指向最后一项数据之后

     isClosed          返回Cursor是否关闭

     isFirst    返回Cursor是否指向第一项数据

     isLast       返回Cursor是否指向最后一项数据

     isNull       返回指定位置的值是否为null

     getCount     返回总的数据项数

     getInt          返回当前行中指定的索引数据

    本文地址:http://www.cnblogs.com/yc-755909659/p/4223999.html 

    PS:本文由J灬叶小超原创,如有转载请注明出处,谢谢!

  • 相关阅读:
    文科妹子都会用 GitHub,你这个工科生还等什么
    阿里巴巴开发手册强制使用SLF4J作为门面担当的秘密,我搞清楚了
    天啦撸!打印日志竟然只晓得 Log4j?
    老板下了死命令,要把日志系统切换到Logback
    根号x的导数,求导方法
    Java内存模型
    loadrunner截取变量的字符串
    loadrunner11回放日志中文乱码解决办法
    软件性能测试的几个主要术语
    什么是自动化测试框架
  • 原文地址:https://www.cnblogs.com/yc-755909659/p/4223999.html
Copyright © 2011-2022 走看看