我有一个Android项目,需要使用从Web服务获取的数据更新listview,但是这些数据将首先保存到本地数据库,然后使用内容提供程序从本地数据库提供给listview。我成功实现了这个要求,只是列表视图显示了相同数据的多个集合。也就是说,如果您运行应用程序5次,列表视图中将显示五组相同的数据。
我的问题是我在哪里以及如何实现某种计数器或循环,以确保只显示一组数据。
以下是我的实施步骤
Fragment使用Loader API从内容加载数据 Provider,这里是onCreateLoader()
public Loader<Cursor> onCreateLoader(int loaderId, Bundle arg) {
return (new CursorLoader(getActivity(), Provider.Programs.CONTENT_URI,
PROJECTION, null, null, null));
}
在onCreateLoader之后,适配器会像这样刷新
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAdapter.swapCursor(cursor);
}
在Content Provider类中,我初始化本地数据库和 调用执行Web服务调用的AsyncTask
public boolean onCreate() {
dbhelper = new LocalDatabase(getContext());
startWebService();
return((dbhelper == null) ? false : true);
}
private void startWebService(){
HttpAsyncTask asyncTask = new HttpAsyncTask();
asyncTask.execute();
}
然后在AsyncTask中我从REST端点获取数据,解析它然后调用Content Provider类的Insert方法将数据添加到数据库并通知提供者数据已更改
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ContentValues values = new ContentValues();
try {
JSONArray jsonArray = new JSONArray(result);
int lenght = jsonArray.length();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String name = jsonObject.getString("name");
values.put(Programs.NAME, name);
insert(Programs.CONTENT_URI, values);
}
Log.i("Data Changed", "Data changed " + lenght);
getContext().getContentResolver().notifyChange(Programs.CONTENT_URI, null);
} catch (JSONException e) {
e.printStackTrace();
}
}
以下是我从数据库中获取数据的方法
@Override
public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
String sort) {
SQLiteQueryBuilder qb=new SQLiteQueryBuilder();
qb.setTables(TABLE);
String orderBy;
if (TextUtils.isEmpty(sort)) {
orderBy=Programs.DEFAULT_SORT_ORDER;
}
else {
orderBy=sort;
}
Cursor c=
qb.query(dbhelper.getReadableDatabase(), new String[]{"_id", "name"}, selection,
selectionArgs, null, null, orderBy);
c.setNotificationUri(getContext().getContentResolver(), url);
return(c);
}
如果您运行应用程序一次,这是有效的,但如果您多次运行它,它将继续提取和复制数据,直到您停止。我在哪里以及如何实现一个计数器,告诉它不要获取或保存或显示相同的数据集。
由于
答案 0 :(得分:0)
对象是否有ID? 该对象是否恰好具有“modified_date”或“created_date”字段?
我认为最好的方法是创建2个列表:1个列表包含服务器中的对象,1个列表包含本地数据库中的对象。然后你只需要通过ID(这应该是唯一的)和/或按日期比较两个列表。
从第一个对象列表(Web服务对象)中删除第二个列表中已有的对象,并仅保存新的对象。或者,如果您有兴趣更新本地的,请更新它们。
答案 1 :(得分:0)
更改您的数据库。添加名为已访问的新字段或默认值为 false 的字段。
当您从数据库中获取数据时,立即将该字段更新为 true 。
所以你的新SQL会是这样的:
SELECT * FROM TABLE1 WHERE accessed = 'false'
答案 2 :(得分:0)
我通过在本地数据库上创建查询查询来修复问题,该查询检查项是否存在并返回类似的布尔值
public boolean ProgramExists(String name) {
db = getReadableDatabase();
Cursor cursor = db.rawQuery("select * from " + PROGRAM_TABLE + " where " + KEY_NAME + "='" + name + "'", null);
boolean exists = false;
if (cursor.moveToFirst()) {
exists = (cursor.getCount() > 0);
}
cursor.close();
return exists;
}
然后我修改了AsyncTask的onPostExecute方法,检查数据库中是否存在该项,如果是,则跳过,如果不是,则添加如下:
protected void onPostExecute(String result) {
super.onPostExecute(result);
ContentValues values = new ContentValues();
try {
JSONArray jsonArray = new JSONArray(result);
int lenght = jsonArray.length();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String name = jsonObject.getString("name");
if (!dbhelper.ProgramExists(name)) {
values.put(Programs.NAME, name);
insert(Programs.CONTENT_URI, values);
}
}
Log.i("Data Changed", "Data changed " + lenght);
getContext().getContentResolver().notifyChange(Programs.CONTENT_URI, null);
} catch (JSONException e) {
e.printStackTrace();
}
}
这解决了问题,并且没有更多重复的条目。