引言
我开始使用SQL数据库,内容提供程序和游标。我正在开发一个应用程序,其中包括:
描述
应用程序以ListActivity开头,其中有一个显示“城市”,“国家”,“年份”的旅行列表,以及“注意”。如果我单击ActionBar的菜单,它会显示create a new travel
的选项(它会启动一个新的活动,其中包含很少的edtitext,其中设置以前的参数和一个要保存的按钮)。如果我长按每个列表项,它会显示一个上下文菜单,其中包含edit
的选项(它将发送到创建新旅行的同一活动)或delete
旅行。
条件
为此,我必须使用ResourceCursorAdapter
。我稍微了解了如何实现 SQLiteOpenHelper 和ContentProvider
,但我不确定如何使用Cursor
来管理活动数据。
故障
我遇到麻烦的是在主要活动中管理数据。我无法更新既不从列表中删除项目,我认为这与我不知道如何使用ID来指示我正在使用的元素有关。
CODE
SQLiteOpenHelper
public class TravelsDatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "travels.db";
public static final String TABLE_NAME = "travels";
public TravelsDatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (" +
Travels._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
Travels.CITY + " TEXT NOT NULL, " +
Travels.COUNTRY + " TEXT NOT NULL, " +
Travels.YEAR + " INTEGER NOT NULL, " +
Travels.NOTE + " TEXT " +
");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < newVersion){
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + ";");
onCreate(db);
}
}
}
ContentProvider
public class TravelsProvider extends ContentProvider {
private static final String AUTHORITY = "com.example.travellist";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/travels");
private TravelsDatabaseHelper mDbHelper;
private SQLiteDatabase database;
//UriMatcher
private static final int URI_TRAVELS = 1;
private static final int URI_TRAVEL_ITEM = 2;
private static final UriMatcher mUriMatcher;
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(AUTHORITY, "travels", URI_TRAVELS);
mUriMatcher.addURI(AUTHORITY, "travels/#", URI_TRAVEL_ITEM);
}
public class Travels implements BaseColumns {
public static final String CITY = "city";
public static final String COUNTRY = "country";
public static final String YEAR = "year";
public static final String NOTE = "notes";
}
@Override
public boolean onCreate() {
mDbHelper = new TravelsDatabaseHelper(getContext());
return true;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
database = mDbHelper.getWritableDatabase();
long id = database.insert(TravelsDatabaseHelper.TABLE_NAME, null, values);
Uri result = null;
if (id >= 0){
result = ContentUris.withAppendedId(CONTENT_URI, id);
getContext().getContentResolver().notifyChange(uri, null);
}
return result;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0;
database = mDbHelper.getWritableDatabase();
int match = mUriMatcher.match(uri);
switch (match){
case URI_TRAVELS:
//nada
break;
case URI_TRAVEL_ITEM:
String id = uri.getPathSegments().get(1);
count = database.update(TravelsDatabaseHelper.TABLE_NAME, values, Travels._ID +
" = " + id + (!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
database = mDbHelper.getWritableDatabase();
int match = mUriMatcher.match(uri);
switch (match){
case URI_TRAVELS:
//nada
break;
case URI_TRAVEL_ITEM:
String id = uri.getPathSegments().get(1);
count = database.delete(TravelsDatabaseHelper.TABLE_NAME, Travels._ID + " = " + id +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
database = mDbHelper.getReadableDatabase();
int match = mUriMatcher.match(uri);
SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
qBuilder.setTables(TravelsDatabaseHelper.TABLE_NAME);
switch (match){
case URI_TRAVELS:
//nada
break;
case URI_TRAVEL_ITEM:
String id = uri.getPathSegments().get(1);
qBuilder.appendWhere(Travels._ID + "=" + id);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
Cursor c = qBuilder.query(database, projection, selection, selectionArgs, null, null, sortOrder);
return c;
}
@Override
public String getType(Uri uri) {
int match = mUriMatcher.match(uri);
switch (match){
case URI_TRAVELS:
return "vnd.android.cursor.dir/vnd.example.travels";
case URI_TRAVEL_ITEM:
return "vnd.android.cursor.item/vnd.example.travels";
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
}
}
MainActivity
public class TravelListActivity extends ListActivity {
private static final int REQUEST_CODE_CREATE_TRAVEL = 0;
private static final int REQUEST_CODE_UPDATE_TRAVEL = 1;
private static final String[] PROJECTION = {Travels._ID, Travels.CITY,
Travels.COUNTRY, Travels.YEAR, Travels.NOTE};
private TravelsCursorAdapter mAdapter;
final class TravelsCursorAdapter extends ResourceCursorAdapter {
private final LayoutInflater mInflater;
public TravelsCursorAdapter(Context context, Cursor c) {
super(context, android.R.layout.simple_list_item_2, c, 0);
mInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = mInflater.inflate(android.R.layout.simple_list_item_2, parent, false);
ViewHolder holder = new ViewHolder();
TextView textView1 = (TextView) view.findViewById(android.R.id.text1);
TextView textView2 = (TextView) view.findViewById(android.R.id.text2);
holder.text1 = textView1;
holder.text2 = textView2;
view.setTag(holder);
return view;
}
@Override
public void bindView(View v, Context context, Cursor c) {
ViewHolder holder = (ViewHolder) v.getTag();
String city = c.getString(c.getColumnIndex(Travels.CITY));
String country = c.getString(c.getColumnIndex(Travels.COUNTRY));
int year = c.getInt(c.getColumnIndex(Travels.YEAR));
String note = c.getString(c.getColumnIndex(Travels.NOTE));
holder.text1.setText(city + " (" + country + ")");
holder.text2.setText(getResources().getString(R.string.year) + " " + year);
}
}
private class ViewHolder {
TextView text1;
TextView text2;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initialData();
getTravelsAdapter();
registerForContextMenu(getListView());
}
public void getTravelsAdapter() {
Cursor c = getContentResolver().query(TravelsProvider.CONTENT_URI, PROJECTION, null, null, null);
mAdapter = new TravelsCursorAdapter(this, c);
setListAdapter(mAdapter);
}
/**
* OptionsMenu
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_new_travel:
Intent intent = new Intent(this, EditTravelActivity.class);
startActivityForResult(intent, REQUEST_CODE_CREATE_TRAVEL);
break;
default:
Toast.makeText(this, "Invalid option", Toast.LENGTH_LONG).show();
break;
}
return super.onMenuItemSelected(featureId, item);
}
/**
* onActivityResult
*/
@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_CODE_CREATE_TRAVEL:
String ncity = data.getExtras().getString(Travels.CITY);
String ncountry = data.getExtras().getString(Travels.COUNTRY);
int nyear = data.getExtras().getInt(Travels.YEAR);
String nnote = data.getExtras().getString(Travels.NOTE);
insertTravel(ncity, ncountry, nyear, nnote);
getTravelsAdapter();
break;
case REQUEST_CODE_UPDATE_TRAVEL:
String ucity = data.getExtras().getString(Travels.CITY);
String ucountry = data.getExtras().getString(Travels.COUNTRY);
int uyear = data.getExtras().getInt(Travels.YEAR);
String unote = data.getExtras().getString(Travels.NOTE);
updateTravel(ucity, ucountry, uyear, unote);
getTravelsAdapter();
break;
}
}
}
/**
* onListItemClick
*/
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this, TravelActivity.class);
intent.putExtra(Travels.CITY, );
intent.putExtra(Travels.COUNTRY, );
intent.putExtra(Travels.YEAR, );
intent.putExtra(Travels.NOTE, );
startActivity(intent);
super.onListItemClick(l, v, position, id);
}
/**
* ContextMenu
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo info;
info = (AdapterView.AdapterContextMenuInfo) menuInfo;
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo menu_info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit_travel:
Intent intent = new Intent(this, EditTravelActivity.class);
startActivityForResult(intent, REQUEST_CODE_UPDATE_TRAVEL);
return true;
case R.id.delete_travel:
deleteTravel(menu_info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
private void initialData(){
insertTravel("Londres", "UK", 2012, "�Juegos Olimpicos!");
insertTravel("Paris", "Francia", 2007, null);
insertTravel("Gotham City", "EEUU", 2011, "��Batman!!");
insertTravel("Hamburgo", "Alemania", 2009, null);
insertTravel("Pekin", "China", 2011, null);
}
private void insertTravel(String city, String country, int year, String note){
ContentValues newValues = new ContentValues();
newValues.put(Travels.CITY, city);
newValues.put(Travels.COUNTRY, country);
newValues.put(Travels.YEAR, year);
newValues.put(Travels.NOTE, note);
getContentResolver().insert(TravelsProvider.CONTENT_URI, newValues);
}
public void updateTravel(String city, String country, int year, String note){
ContentValues updateValues = new ContentValues();
updateValues.put(Travels.CITY, city);
updateValues.put(Travels.COUNTRY, country);
updateValues.put(Travels.YEAR, year);
updateValues.put(Travels.NOTE, note);
getContentResolver().update(TravelsProvider.CONTENT_URI, updateValues, null, null);
}
private void deleteTravel(long id){
getContentResolver().delete(TravelsProvider.CONTENT_URI, Travels._ID+"="+id, null);
}
public ArrayList<TravelInfo> getTravelsList(){
ArrayList<TravelInfo> travels = new ArrayList<TravelInfo>();
Cursor c = getContentResolver().query(TravelsProvider.CONTENT_URI,
null, null, null, Travels.YEAR);
if (c != null && c.moveToFirst()){
int cityIndex = c.getColumnIndex(Travels.CITY);
int countryIndex = c.getColumnIndex(Travels.COUNTRY);
int yearIndex = c.getColumnIndex(Travels.YEAR);
int noteIndex = c.getColumnIndex(Travels.NOTE);
do {
String city = c.getString(cityIndex);
String country = c.getString(countryIndex);
int year = c.getInt(yearIndex);
String note = c.getString(noteIndex);
TravelInfo travel = new TravelInfo(city, country, year, note);
travels.add(travel);
}
while (c.moveToNext());
c.close();
}
return travels;
}
}