android-SQLite 和 Content

SQLite

游标(Cursor)相当于指向底层数据中结果集的指针,而不是提取和返回结果值的副本,是在结果集中对位置(行)进行控制的管理方式。

moveToFirst:把游标移动到查询结果的第一行

moveToNext:把游标移动到下一行

moveToPrevious:把游标移动到前一行

getCount:返回结果集中的行数

getColumnIndexOrThrow:返回具有指定名称的列的索引

getColumnName:返回指定索引的列的名称

getColumnNames:返回当前游标中的所有列名的字符串数组

moveToPosition:移动到特定的行的游标

getPosition:返回当前的游标位置

 

Adapter类负责管理数据库交互(数据模型,更具对象属性设置增删改查的逻辑),使用SQLiteOpenHelper的扩展类协助创建数据表,获取SQLiteDatabase对象进行增删改查。

扩展SQLiteOpenHelper,由扩展类完成数据表的创建,数据库的更新。

package com.paad.todolist;

import java.util.Date;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;

public class ToDoDBAdapter {
  private static final String DATABASE_NAME = "todoList.db";
  private static final String DATABASE_TABLE = "todoItems";
  private static final int DATABASE_VERSION = 1;
 
  public static final String KEY_ID = "_id";
  public static final String KEY_TASK = "task";
  public static final String KEY_CREATION_DATE = "creation_date";
  
  private SQLiteDatabase db;
  private final Context context;
  private toDoDBOpenHelper dbHelper;

  public ToDoDBAdapter(Context _context) {
    this.context = _context;
    dbHelper = new toDoDBOpenHelper(context, DATABASE_NAME, 
                                    null, DATABASE_VERSION);
  }
  
  public void close() {
    db.close();
  }
  
  public void open() throws SQLiteException {  
    try {
      db = dbHelper.getWritableDatabase();
    } catch (SQLiteException ex) {
      db = dbHelper.getReadableDatabase();
    }
  }  
  
  //Insert a new task
  public long insertTask(ToDoItem _task) {
    // Create a new row of values to insert.
    ContentValues newTaskValues = new ContentValues();
    // Assign values for each row.
    newTaskValues.put(KEY_TASK, _task.getTask());
    newTaskValues.put(KEY_CREATION_DATE, _task.getCreated().getTime());
    // Insert the row.
    return db.insert(DATABASE_TABLE, null, newTaskValues);
  }

  // Remove a task based on its index
  public boolean removeTask(long _rowIndex) {
    return db.delete(DATABASE_TABLE, KEY_ID + "=" + _rowIndex, null) > 0;
  }

  // Update a task
  public boolean updateTask(long _rowIndex, String _task) {
    ContentValues newValue = new ContentValues();
    newValue.put(KEY_TASK, _task);
    return db.update(DATABASE_TABLE, newValue, KEY_ID + "=" + _rowIndex, null) > 0;
  }
  
  public Cursor getAllToDoItemsCursor() {
    return db.query(DATABASE_TABLE, 
                    new String[] { KEY_ID, KEY_TASK, KEY_CREATION_DATE}, 
                    null, null, null, null, null);
  }

  public Cursor setCursorToToDoItem(long _rowIndex) throws SQLException {
    Cursor result = db.query(true, DATABASE_TABLE, 
                               new String[] {KEY_ID, KEY_TASK},
                             KEY_ID + "=" + _rowIndex, null, null, null, 
                             null, null);
    if ((result.getCount() == 0) || !result.moveToFirst()) {
      throw new SQLException("No to do items found for row: " + _rowIndex);
    }
    return result;
  }

  public ToDoItem getToDoItem(long _rowIndex) throws SQLException {
    Cursor cursor = db.query(true, DATABASE_TABLE, 
                             new String[] {KEY_ID, KEY_TASK},
                             KEY_ID + "=" + _rowIndex, null, null, null, 
                             null, null);
    if ((cursor.getCount() == 0) || !cursor.moveToFirst()) {
      throw new SQLException("No to do item found for row: " + _rowIndex);
    }

    String task = cursor.getString(cursor.getColumnIndex(KEY_TASK));
    long created = cursor.getLong(cursor.getColumnIndex(KEY_CREATION_DATE));
          
    ToDoItem result = new ToDoItem(task, new Date(created));
    return result;  
  }
  
  private static class toDoDBOpenHelper extends SQLiteOpenHelper {

      public toDoDBOpenHelper(Context context, String name,
                              CursorFactory factory, int version) {
        super(context, name, factory, version);
      }

      // SQL Statement to create a new database.
      private static final String DATABASE_CREATE = "create table " + 
        DATABASE_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " +
        KEY_TASK + " text not null, " + KEY_CREATION_DATE + " long);";

      @Override
      public void onCreate(SQLiteDatabase _db) {
        _db.execSQL(DATABASE_CREATE);
      }

      @Override
      public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {
        Log.w("TaskDBAdapter", "Upgrading from version " + 
                               _oldVersion + " to " +
                               _newVersion + ", which will destroy all old data");

        // Drop the old table.
        _db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
        // Create a new one.
        onCreate(_db);
      }
    }
}

 

Content

ContentProvider可使用SQLiteOpenHelper辅助操作数据(用数据库持久化)。由ContentProvider的扩展类完成数据交互,ContentProvider扩展类的对象则是通过获取到应用上下文中的ContentResolver对象,根据其方法及URI,由系统内部执行ContentProvider扩展类对象中重写的方法。

ContentProvider扩展类的实现:

public class EarthquakeProvider extends ContentProvider {

  public static final Uri CONTENT_URI = Uri.parse("content://com.paad.provider.earthquake/earthquakes");
  
  @Override
  public boolean onCreate() {
    Context context = getContext();

    earthquakeDatabaseHelper dbHelper = new earthquakeDatabaseHelper(context,  
                                                                   DATABASE_NAME, 
                                                                   null, 
                                                                   DATABASE_VERSION);
    earthquakeDB = dbHelper.getWritableDatabase();
    return (earthquakeDB == null) ? false : true;
  }
    
  @Override
  public Cursor query(Uri uri, 
                      String[] projection, 
                      String selection, 
                      String[] selectionArgs, 
                      String sort) {
        
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

    qb.setTables(EARTHQUAKE_TABLE);

    // If this is a row query, limit the result set to the passed in row. 
    switch (uriMatcher.match(uri)) {
      case QUAKE_ID: qb.appendWhere(KEY_ID + "=" + uri.getPathSegments().get(1));
                     break;
      default      : break;
    }

    // If no sort order is specified sort by date / time
    String orderBy;
    if (TextUtils.isEmpty(sort)) {
      orderBy = KEY_DATE;
    } else {
      orderBy = sort;
    }

    // Apply the query to the underlying database.
    Cursor c = qb.query(earthquakeDB, 
                        projection, 
                        selection, selectionArgs, 
                        null, null, 
                        orderBy);

    // Register the contexts ContentResolver to be notified if
    // the cursor result set changes. 
    c.setNotificationUri(getContext().getContentResolver(), uri);
    
    // Return a cursor to the query result.
    return c;
  }

  @Override
  public Uri insert(Uri _uri, ContentValues _initialValues) {
    // Insert the new row, will return the row number if 
    // successful.
    long rowID = earthquakeDB.insert(EARTHQUAKE_TABLE, "quake", _initialValues);
          
    // Return a URI to the newly inserted row on success.
    if (rowID > 0) {
      Uri uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
      getContext().getContentResolver().notifyChange(uri, null);
      return uri;
    }
    throw new SQLException("Failed to insert row into " + _uri);
  }

  @Override
  public int delete(Uri uri, String where, String[] whereArgs) {
    int count;
    
    switch (uriMatcher.match(uri)) {
      case QUAKES:
        count = earthquakeDB.delete(EARTHQUAKE_TABLE, where, whereArgs);
        break;

      case QUAKE_ID:
        String segment = uri.getPathSegments().get(1);
        count = earthquakeDB.delete(EARTHQUAKE_TABLE, KEY_ID + "="
                                    + segment
                                    + (!TextUtils.isEmpty(where) ? " AND (" 
                                    + where + ‘)‘ : ""), whereArgs);
        break;

      default: throw new IllegalArgumentException("Unsupported URI: " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return count;
  }

  @Override
  public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
    int count;
    switch (uriMatcher.match(uri)) {
      case QUAKES: count = earthquakeDB.update(EARTHQUAKE_TABLE, values, 
                                               where, whereArgs);
                   break;

      case QUAKE_ID: String segment = uri.getPathSegments().get(1);
                     count = earthquakeDB.update(EARTHQUAKE_TABLE, values, KEY_ID 
                             + "=" + segment 
                             + (!TextUtils.isEmpty(where) ? " AND (" 
                             + where + ‘)‘ : ""), whereArgs);
                     break;

      default: throw new IllegalArgumentException("Unknown URI " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return count;
  }
  
  @Override
  public String getType(Uri uri) {
    switch (uriMatcher.match(uri)) {
      case QUAKES: return "vnd.android.cursor.dir/vnd.paad.earthquake";
      case QUAKE_ID: return "vnd.android.cursor.item/vnd.paad.earthquake";
      default: throw new IllegalArgumentException("Unsupported URI: " + uri);
    }
  }
  
  // Create the constants used to differentiate between the different URI 
  // requests.
  private static final int QUAKES = 1;
  private static final int QUAKE_ID = 2;

  private static final UriMatcher uriMatcher;

  // Allocate the UriMatcher object, where a URI ending in ‘earthquakes‘ will
  // correspond to a request for all earthquakes, and ‘earthquakes‘ with a 
  // trailing ‘/[rowID]‘ will represent a single earthquake row.
  static {
   uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
   uriMatcher.addURI("com.paad.provider.Earthquake", "earthquakes", QUAKES);
   uriMatcher.addURI("com.paad.provider.Earthquake", "earthquakes/#", QUAKE_ID);
  }
  
  //The underlying database
  private SQLiteDatabase earthquakeDB;

  private static final String TAG = "EarthquakeProvider";
  private static final String DATABASE_NAME = "earthquakes.db";
  private static final int DATABASE_VERSION = 1;
  private static final String EARTHQUAKE_TABLE = "earthquakes";

  // Column Names
  public static final String KEY_ID = "_id";
  public static final String KEY_DATE = "date";
  public static final String KEY_DETAILS = "details";
  public static final String KEY_LOCATION_LAT = "latitude";
  public static final String KEY_LOCATION_LNG = "longitude";
  public static final String KEY_MAGNITUDE = "magnitude";
  public static final String KEY_LINK = "link";

  // Column indexes
  public static final int DATE_COLUMN = 1;
  public static final int DETAILS_COLUMN = 2;
  public static final int LONGITUDE_COLUMN = 3;
  public static final int LATITUDE_COLUMN = 4;
  public static final int MAGNITUDE_COLUMN = 5;
  public static final int LINK_COLUMN = 6;
      
  // Helper class for opening, creating, and managing database version control
  private static class earthquakeDatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_CREATE =
      "create table " + EARTHQUAKE_TABLE + " (" 
      + KEY_ID + " integer primary key autoincrement, "
      + KEY_DATE + " INTEGER, "
      + KEY_DETAILS + " TEXT, "
      + KEY_LOCATION_LAT + " FLOAT, "
      + KEY_LOCATION_LNG + " FLOAT, "
      + KEY_MAGNITUDE + " FLOAT), "
      + KEY_LINK + " TEXT);";
        
    public earthquakeDatabaseHelper(Context context, String name,
                                    CursorFactory factory, int version) {
      super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
      db.execSQL(DATABASE_CREATE);           
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
      Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                  + newVersion + ", which will destroy all old data");
              
      db.execSQL("DROP TABLE IF EXISTS " + EARTHQUAKE_TABLE);
      onCreate(db);
    }
  }
}

ContentProvider扩展类的使用:

private void loadQuakesFromProvider() {
      // Clear the existing earthquake array
      earthquakes.clear();

      ContentResolver cr = getContentResolver();

      // Return all the saved earthquakes
      Cursor c = cr.query(EarthquakeProvider.CONTENT_URI, null, null, null, null);
         
      if (c.moveToFirst()) {
        do { 
          // Extract the quake details.
          Long datems = c.getLong(EarthquakeProvider.DATE_COLUMN);
          String details = c.getString(EarthquakeProvider.DETAILS_COLUMN);
          Float lat = c.getFloat(EarthquakeProvider.LATITUDE_COLUMN);
          Float lng = c.getFloat(EarthquakeProvider.LONGITUDE_COLUMN);
          Double mag = c.getDouble(EarthquakeProvider.MAGNITUDE_COLUMN);
          String link = c.getString(EarthquakeProvider.LINK_COLUMN);

          Location location = new Location("dummy");
          location.setLongitude(lng);
          location.setLatitude(lat);

          Date date = new Date(datems);

          Quake q = new Quake(date, details, location, mag, link);
          addQuakeToArray(q);
        } while(c.moveToNext());
      }
 }


private void addNewQuake(Quake _quake) {
      ContentResolver cr = getContentResolver();
      // Construct a where clause to make sure we don?t already have this 
      // earthquake in the provider.
      String w = EarthquakeProvider.KEY_DATE + " = " + _quake.getDate().getTime();

      // If the earthquake is new, insert it into the provider.
      if (cr.query(EarthquakeProvider.CONTENT_URI, null, w, null, null).getCount()==0){
        ContentValues values = new ContentValues();    

        values.put(EarthquakeProvider.KEY_DATE, _quake.getDate().getTime());
        values.put(EarthquakeProvider.KEY_DETAILS, _quake.getDetails());

        double lat = _quake.getLocation().getLatitude();
        double lng = _quake.getLocation().getLongitude();
        values.put(EarthquakeProvider.KEY_LOCATION_LAT, lat);
        values.put(EarthquakeProvider.KEY_LOCATION_LNG, lng);
        values.put(EarthquakeProvider.KEY_LINK, _quake.getLink());
        values.put(EarthquakeProvider.KEY_MAGNITUDE, _quake.getMagnitude());

        cr.insert(EarthquakeProvider.CONTENT_URI, values);
        earthquakes.add(_quake);

        addQuakeToArray(_quake);
      }
}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。