我有这个简单的应用程序,我目前正在写作练习。其目的是允许用户在服务器上发送报价和该报价的作者(在这种情况下是我已经注册的Parse.com后端),然后随机地向应用的其他用户显示这些报价。因此,通过打开应用程序,您会收到某人发布的随机评论。
我试图实现这个目标的方式是:
在启动时,应用程序连接到Parse.com后端并下载所有当前可用的引号(我称之为Inanity对象,因为引用应该是开明的,但实际上应该是愚蠢和无意义的 - 无论如何,不没问题。这是代码:
query.findInBackground(new FindCallback<ParseObject>() {
SQLi sqlite = new SQLi(MainActivity.this);
SQLiteDatabase dbz = sqlite.getWritableDatabase();
@Override
public void done(List<ParseObject> list, ParseException e) {
//sqlite.dbDelete();
if (e == null) {
int size = list.size();
for (int i = 0; i < size; i++) {
ParseObject object = list.get(i);
String author = object.get("author").toString();
String content = object.get("content").toString();
Inanity inan = new Inanity(content, author, 1);
Log.d("FOR LOOP" + i, inan.toString());
sqlite.insertInanity(dbz, inan);
}
}
}
});
非常简单。 ( dbz 是顺便调用 getWritableDatabase()获取的SQLiteDatabase)。下面的代码是SQLiteOpenHelper insertInanity()方法的代码,我用它将来自服务器的检索数据放在本地SQLite数据库中:
public void insertInanity(SQLiteDatabase db, Inanity inanity) {
ContentValues values = new ContentValues();
values.put(CONTENT_INANITIES, inanity.getContent());
values.put(AUTHOR_INANITIES, inanity.getAuthor());
values.put(UPVOTE_INANITIES, inanity.getUpvotes());
db.insert(TABLE_INANITIES, null, values);
}
我将一个SQLiteDatabase对象传递给该方法只是为了避免必须调用getWriteableDatabase() - 如果我一直这样做,我在重复调用时遇到了一些麻烦。
在本地SQLite数据库上写入服务器数据之后,用户将被带到一个Activity,该Activity开始在几个TextView中显示引号和引号的作者。这是从SQLite数据库中检索引用/作者对象的代码:
public Inanity retrieveInanity(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_INANITIES, new String[] {
CONTENT_INANITIES, AUTHOR_INANITIES, UPVOTE_INANITIES },
ID_INANITIES + " = " + id, null, null, null, null);
if (cursor == null || cursor.getCount() == 0) {
return new Inanity("a", "b", 1);
}
else {
cursor.moveToFirst();
String contentL = cursor.getString(cursor
.getColumnIndex(CONTENT_INANITIES));
String authorL = cursor.getString(cursor
.getColumnIndex(AUTHOR_INANITIES));
int upvotesL = cursor.getInt(cursor
.getColumnIndex(UPVOTE_INANITIES));
Inanity inanity = new Inanity(contentL, authorL, upvotesL);
return inanity;
}
}
最后,要显示的引用是从本地存储的结果中随机选择的(“a”是先前声明的int变量)
final SQLi sql = new SQLi(this);
a = sql.getRowCount() + 1;
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Random rand = new Random();
int e = rand.nextInt(a);
if (e != 0) {
Inanity inanity = sql.retrieveInanity(e);
String content = inanity.getContent();
String author = inanity.getAuthor();
ImageView imageView = (ImageView) findViewById(R.id.downloaded);
TextView contentView = (TextView) findViewById(R.id.content);
TextView authorView = (TextView) findViewById(R.id.author);
Picasso.with(ShowActivity.this)
.load("http://img1.etsystatic.com/000/0/5356113/il_fullxfull.314192275.jpg")
.into(imageView);
contentView.setAlpha(0.9f);
authorView.setAlpha(0.9f);
Animation alpha = new AlphaAnimation(0.1f, 1.0f);
alpha.setDuration(2000);
contentView.setText(content);
authorView.setText(author);
contentView.startAnimation(alpha);
authorView.startAnimation(alpha);
}
else {
Toast.makeText(ShowActivity.this,
"Cursor trouble in wonderland!", Toast.LENGTH_LONG)
.show();
}
}
});
}
SQLi类的 getRowCount()方法是这样的:
public int getRowCount() {
int count = 1;
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_INANITIES, null);
if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
count = cursor.getCount();
}
return count;
}
大部分时间。这很棒。那么,问题是什么,我听到你的问题?好吧,因为每次应用程序启动时我想刷新引号并从服务器获取新的引号,我试图完成的方法是删除数据库的Inanity表的内容并重新填充它们启动。所以,我在SQLi数据库助手类中创建了这个方法,该类称为 dbDelete(),我在FindCallback类的 done()方法的开头调用了该方法。 Parse.com库(尽管我已经从这段代码中对此进行了评论,它可以游戏地工作:它可以很好地删除数据库的内容)。不幸的是,当我这样做时,似乎本地SQLite数据库没有在应用程序启动时因某些地狱原因而重新填充,所以我不断获得占位符“a”,“b”和 retrieveInanity时返回的1个值()方法无法找到游标内容。这是 dbDelete()方法,非常简单:
public void dbDelete() {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_INANITIES, null, null);
}
我一直试图解决这个问题已经有一段时间了,这让我发疯了。我理解这个问题很复杂,很大,并且它不包含任何吸引人的NullPointerExceptions / logcat动作,但任何帮助都将不胜感激。我必须遗漏与SQLite数据库使用明显相关的东西,但我根本无法理解。
答案 0 :(得分:2)
我写了一个类似的应用程序(一个调用远程数据库并更新本地数据库的信息)。您应该尝试使用db.insertOrThrow
。您需要将该方法包装在Try ... Catch语句中。它将尝试插入行,并在行已存在时抛出异常。然后,您可以通过将Catch部件留空来忽略错误。这将避免删除和重建表。
try {
db.insertOrThrow(TABLE_INANITIES, null, values);
} catch SQLException s {
\\do nothing, as we don't care about existing rows
}
如果您将报价服务器设置为具有报价的唯一标识符,则本地副本(您的SQLite DB)将不会插入重复的条目。例如,服务器上的引用数据库表看起来像这样
ID | Quote | Author
1 | blah | J. smith
将列ID
设置为唯一标识符(或唯一键)。当您的应用程序调用服务器并查询远程数据库时,您的本地数据库只会添加不存在的记录。
我还想确保您在onResume()中更新游标适配器。