I have a ContentProvider. There are my query and insert methods:
@Override
public Uri insert(Uri uri, ContentValues values) {
    final int match = sUriMatcher.match(uri);
    long id = -1;
    switch (match) {
        case ARTICLES_LIST:
            id = ArticlesDataSource.getInstance().addArticle(values);
            break;
    }
    Log.d(LOG_TAG, "Notify change for URI: " + uri);
    getContext().getContentResolver().notifyChange(uri, null);
    if (id != -1) {
        return ArticleContract.buildArticleWithIdUri(id);
    }
    return null;
}
and
 @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    final int match = sUriMatcher.match(uri);
    Cursor refCursor = null;
    switch (match) {
        case ARTICLES_LIST:
            refCursor = ArticlesDataSource.getInstance().getAllPreviewArticlesCursor(selectionArgs, selection, selectionArgs, sortOrder);
            break;
        case ARTICLES_LIST_BY_CATEGORY:
            Article.Category category = ArticleContract.getCategoryFromUri(uri);
            refCursor = ArticlesDataSource.getInstance().getPreviewArticlesCursorByCategory(selectionArgs, selection, selectionArgs, sortOrder, category);
            //Modify uri for correct listener behaviour. Full uri is: content://payspace.ssidit.pp.ua.payspacemagazine/articles/category/categoryName
            List<String> segments = uri.getPathSegments();
            String lastSegment = segments.get(segments.size() - 2);
            String uriStr = uri.toString();
            uri = Uri.parse(uriStr.substring(0, uriStr.indexOf(lastSegment) - 1));
            break;
        default:
            throw new UnsupportedOperationException("Unknwon uri: " + uri);
    }
    Log.d(LOG_TAG, "Registered for observe changes in uri: " + uri.toString());
    refCursor.setNotificationUri(getContext().getContentResolver(), uri);
    return refCursor;
}
My logs for notifyChange() and setNotificationUri():
Registered for observe changes in uri: content://payspace.ssidit.pp.ua.payspacemagazine/articles
Notify change for URI: content://payspace.ssidit.pp.ua.payspacemagazine/articles
As you can see, uris are equal. Content adds to the database. I don't close a cursor in my code. What can be wrong?
Update1: How I contruct and deal with CursorAdapter. When the app starts, it calls:
mListAdapter = new SimpleCursorAdapter(getActivity(), R.layout.article_list_item, null, from, to, 0);
Then I load some data from database. Code of DatabaseCursorLoader:
public class DatabaseCursorLoader extends CursorLoader {
public static final String LOG_TAG = DatabaseCursorLoader.class.getName();
private int limit;
private Article.Category category;
public DatabaseCursorLoader(Context context, Article.Category category, int limit) {
    super(context);
    this.category = category;
    this.limit = limit;
}
@Override
public Cursor loadInBackground() {
    return getContext().getContentResolver().query(ArticleContract.buildArticlesWithCategoryUri(category), ArticlesDataSource.previewColumns, null, null, Article.KEY_DATE + " DESC LIMIT " + limit);
}
}
and swap the cursor:
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    int id = loader.getId();
    switch (id) {
        case LOADER_PREVIEWS_DB:
            int loaded = cursor.getCount();
            Log.d(LOG_TAG, "Rows in cursor " + loaded);
            //если мы ничего не загрузили (не осталось новых записей из БД)
            if (loaded - wasLoaded == 0) {
                Log.d(LOG_TAG, "Starting service to load new data");
                Intent intent = new Intent(getActivity(), LoadPreviewsService.class);
                intent.putExtra(Article.KEY_CATEGORY, mCurrentCategory.ordinal());
                intent.putExtra(Article.KEY_PAGE, mCurrentPage);
                getActivity().startService(intent);
            }
            wasLoaded = loaded;
            Log.d(LOG_TAG, "Swapped cursor");
            mListAdapter.swapCursor(cursor);
            break;
    }
}
Update2: The problem was that I've extended CursorLoader class so I think I needed to override some extra methods for correct work. I just changed:
loader = new DatabaseCursorLoader(getActivity(), category, page * ARTICLES_PER_PAGE);
to
loader = new CursorLoader(getActivity(), ArticleContract.buildArticlesWithCategoryUri(category), ArticlesDataSource.previewColumns, null, null, Article.KEY_DATE + " DESC LIMIT " + (page * ARTICLES_PER_PAGE));
and it worked. Big thanks to @pskink!
