via usar teclado para inalambrico externo configurar conectar como celular android database cursor android-contentprovider android-contentresolver

android - teclado - usar celular como mouse via usb



¿Para qué se utiliza el cursor.setNotificationUri()? (3)

Hice una investigación sobre cómo usar ContentProviders y Loaders en este tutorial

Cómo lo veo: tenemos una Activity con ListView , SimpleCursorAdapter y CursorLoader . También implementamos ContentProvider .

En una Activity podemos llamar a getContentResolver().insert(URI, contentValues); a través de un botón de clic.

En nuestra implementación de ContentProvider , al final del método insert() , llamamos getContentResolver().notifyChange(URI, null); y nuestro CursorLoader recibirá un mensaje de que debe recargar los datos y actualizar la interfaz de usuario. Además, si usamos FLAG_REGISTER_CONTENT_OBSERVER en SimpleCursorAdapter , también recibirá un mensaje y se onContentChanged() su método onContentChanged() .

Por lo tanto, nuestro ListView se actualizará si insertamos, actualizamos o eliminamos datos.

Activity.startManagingCursor(cursor); está en desuso, cursor.requery() desuso, por lo que no veo ningún sentido cursor.setNotificationUri() de cursor.setNotificationUri() .

Busqué en el código fuente del método setNotificationUri() y vi que llama a mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver) dentro del método. También CursorLoader hace lo mismo. Finalmente el cursor recibirá un mensaje y se llamará al siguiente método dentro del Cursor:

protected void onChange(boolean selfChange) { synchronized (mSelfObserverLock) { mContentObservable.dispatchChange(selfChange, null); // ... } }

Pero no puedo darle sentido a esto.

Entonces, mi pregunta es: ¿por qué deberíamos llamar cursor.setNotificationUri() en el método de query() de nuestra implementación ContentProvider ?


Si llama a Cursor.setNotificationUri() , el Cursor sabrá para qué ContentProvider Uri fue creado.

CursorLoader registra su propio ForceLoadContentObserver (que extiende ContentObserver ) con el ContentResolver de ContentResolver para el URI que especificó al llamar a setNotificationUri .

Entonces, una vez que ContentResolver sepa que el contenido de URI ha cambiado [esto sucede cuando llama a getContext().getContentResolver().notifyChange(uri, contentObserver); dentro de los métodos Insert insert() , update() y delete() ContentProvider , notifica a todos los observadores, incluido ForceLoadContentObserver de ForceLoadContentObserver .

ForceLoadContentObserver luego marca mContentChanged del cargador como verdadero


Yo uso un URI para el adaptador de cursor.

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = new Bundle(); Uri uri = TemperatureContract.SensorEntry.buildSensorID0AddressUri(mDeviceAddress); args.putParcelable("URI", uri); getSupportLoaderManager().initLoader(0, args, this); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { if (args != null) { Uri mUri = args.getParcelable("URI"); return new CursorLoader(this, mUri, null, // projection null, // selection null, // selectionArgs null); // sortOrder } else { return null; } }

En otra clase, uso un URI diferente para cambiar el contenido de la base de datos . Para actualizar mi vista, tuve que cambiar la implementación predeterminada del método de update del proveedor de datos. La implementación predeterminada solo notifica el mismo URI. Tengo que notificar a otro URI.

Terminé llamando a la notifyChange() dos veces en mi clase de proveedor de datos, en el método de update :

@Override public int update( Uri uri, ContentValues values, String selection, String[] selectionArgs) { final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); final int match = sUriMatcher.match(uri); int rowsUpdated; switch (match) { case ...: break; case SENSOR_BY_ID_AND_ADDRESS: String sensorId = TemperatureContract.SensorEntry.getSensorIdFromUri(uri); String sensorAddress = TemperatureContract.SensorEntry.getSensorAddressFromUri(uri); rowsUpdated = db.update( TemperatureContract.SensorEntry.TABLE_NAME, values, "sensorid = ? AND address = ?", new String[]{sensorId, sensorAddress}); if (rowsUpdated != 0) { Uri otheruri = TemperatureContract.SensorEntry.buildSensorID0AddressUri(sensorAddress); getContext().getContentResolver().notifyChange(otheruri, null); } break; case ...: break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); } if (rowsUpdated != 0) { getContext().getContentResolver().notifyChange(uri, null); } return rowsUpdated;

Hice lo mismo para los métodos de insert y delete .


CursorLoader registra el observador para el cursor, no para el URI.

Mire el código fuente de CursorLoader a continuación. Observe que CursorLoader registra contentObserver en el cursor .

/* Runs on a worker thread */ @Override public Cursor loadInBackground() { synchronized (this) { if (isLoadInBackgroundCanceled()) { throw new OperationCanceledException(); } mCancellationSignal = new CancellationSignal(); } try { Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection, mSelectionArgs, mSortOrder, mCancellationSignal); if (cursor != null) { try { // Ensure the cursor window is filled. cursor.getCount(); cursor.registerContentObserver(mObserver); } catch (RuntimeException ex) { cursor.close(); throw ex; } } return cursor; } finally { synchronized (this) { mCancellationSignal = null; } }

El Cursor debe llamar al método setNotificationUri() para registrar mSelfObserver en el uri .

//AbstractCursor.java public void setNotificationUri(ContentResolver cr, Uri notifyUri, int userHandle) { synchronized (mSelfObserverLock) { mNotifyUri = notifyUri; mContentResolver = cr; if (mSelfObserver != null) { mContentResolver.unregisterContentObserver(mSelfObserver); } mSelfObserver = new SelfContentObserver(this); mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver, userHandle); // register observer to the uri mSelfObserverRegistered = true; } }

Dentro de los métodos de insert , update y delete getContext().getContentResolver().notifyChange(uri, null); , debe llamar a getContext().getContentResolver().notifyChange(uri, null); Para notificar cambios a los observadores uri .

Entonces, si no llama al cursor#setNotificationUri() , su CursorLoader no recibirá una notificación si los datos subyacentes a esa uri cambian.