3

一些背景资料:ContentResolver.notifyChange()不工作

当我运行我的应用程序,从我的本地SQLite数据库缓存信息的前台活动的显示器,同时后台服务连接到服务器,并得到一些新鲜的信息。当数据被检索时,服务启动我的ContentProvider的插入方法,以更新我的本地SQLite数据库。插入完成后,我通知我的ContentObserver(前台活动)有关刷新视图的更改。

我知道插入工作正常,因为当我手动重新运行应用程序时,我可以在屏幕上看到新数据。不幸的是,自动刷新不起作用。调用方法ContentObserver.notifyChange()失败。最奇怪的是,它甚至没有停止在catch (Exception e)线上。它直接在try/catch区块之外。我不知道发生了什么事。 LogCat,和控制台很安静。

以下是我的ContentProvider中负责插入和更改通知的insert方法中的部分代码。

SQLiteDatabase sqlDB = db.getWritableDatabase(); 
try { 
    long newID = sqlDB.insertOrThrow(StatsCollectorDatabase.TABLE_USERS, null, values); 
    if (newID > 0) { 
     Uri newUri = ContentUris.withAppendedId(uri, newID); 
     ContentResolver contentResolver = getContext().getContentResolver(); 
     contentResolver.notifyChange(uri, null); // This is the line that fails 
     return newUri; 
    } else { 
     throw new SQLException("Failed to insert row into " + uri); 
    } 
} catch (SQLiteConstraintException e) { 
    Log.i(DEBUG_TAG, "Ignoring constraint failure."); 
} catch (Exception e) { 
    Log.i(DEBUG_TAG, e.getLocalizedMessage()); 
} 

下面是onCreate方法在前台活动代码:

Cursor cursor = this.managedQuery(StatsCollectorProvider.CONTENT_URI, null, null, null, null); 
String[] columns = new String[] { StatsCollectorDatabase._USER_NAME, StatsCollectorDatabase._USER_DEVICE_ID }; 
int[] views = new int[] { R.id.name_entry, R.id.number_entry }; 

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this.getApplicationContext(), R.layout.list_item, cursor, columns, views, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); 
this.setListAdapter(adapter); 

Intent intent = new Intent(this.getApplicationContext(), UsersDownloaderService.class); 
this.startService(intent);  

我试着用搜索引擎,但没有发现任何有关。我该如何解决这个问题?

我可以提供更多的代码,如果这是必要的。

+1

您是否对'managedQuery'和'notifyChange'使用了相同的基本URL? 我有类似的代码实例化'SimpleCursorAdapter'没有标志,也许你可以尝试省略最后一个参数... – ge0rg

+0

感谢提示,但它不是它。虽然,对你而言,赞成先生,因为你是唯一参与我的问题的人;) – Moyshe

回答

2

我解决了它。我的活动没有继承FragmentActivity,而且我的布局没有包含任何片段,所以它无法工作 - 没有任何已注册的ContentObservers。

现在看起来是这样的:

首先主要活动起飞,注册片段布局和启动后台服务在它的onCreate方法:

super.onCreate(savedInstanceState); 
setContentView(R.layout.list); 

Intent intent = new Intent(this.getApplicationContext(), UsersDownloaderService.class); 
this.startService(intent); 

这是我list布局:

<?xml version="1.0" encoding="utf-8"?> 
<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
    class="org.moyshe.cursors.ListViewFragment" 
    android:name="org.moyshe.cursors.ListViewFragment" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 
</fragment> 

ListViewFragment延伸ListFragment和实现LoaderCallbacks<Cursor>。这是我错过的ContentObserver。如果有人对它的外观感兴趣,请阅读这个article - 它对我有很大的帮助。

我的服务和ContentProvider类没有更改。

1

我有一个类似的问题,发现solution here

简而言之,事实证明我需要在我的内容提供商的query()方法返回的光标上调用setNotificationUri(ContentResolver cr, Uri uri)