【讀書筆記《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灬葉小超原創,如有轉載請注明出處,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM