Frage

Das Ziel: Refresh-Datenbank von XML-Daten

Der Prozess:

  • Starten Sie die Transaktion
  • Löschen alle vorhandenen Zeilen aus den Tabellen
  • Per jedes Hauptelement der geparsten XML Einsatz Zeile in Haupttabelle und bekommen PK
  • Per jedes Kind des Hauptelementes Einsatz Datensatz in die 2. Tabelle FK aus dem vorherigen Schritt der Bereitstellung
  • Commit-Transaktion

ziemlicher Standard so weit wie db-Operationen. Das Problem ist, dass CRUD-Operationen nicht innerhalb ContentProvider getan werden, sondern ContentResolver so der Einsatz zum Beispiel sieht aus wie resolver.insert(CONTENT_URI, contentValues) verwenden. Die ContentResolver API scheint nicht, etwas zu Transaktion haben betraf und ich kann nicht bulkInsert verwenden, da ich mit Unterbrechungen in zwei Tabellen eingefügt bin (plus Ich möchte delete innerhalb der Transaktion als auch haben).

Ich dachte an meine maßgeschneiderte ContentProvider als Zuhörer Registrierung von registerContentObserver verwenden, aber da ContentResolver#acquireProvider Methoden versteckt sind, wie erhalte ich die richtige Referenz?

Bin ich kein Glück?

War es hilfreich?

Lösung

Ich habe, dass sie im Quellcode von Google I / O-Anwendung gesehen, ContentProvider die applyBatch() Verfahren und die Verwendung Transaktionen in der es außer Kraft setzen. So erstellen Sie eine Charge von ContentProviderOperation s und dann Aufruf getContentResolver().applyBatch(uri_authority, batch).

Ich plane, diesen Ansatz zu verwenden, um zu sehen, wie es funktioniert. Ich bin gespannt, ob jemand es versucht hat.

Andere Tipps

Es ist möglich, transaktionsbasierte Multi-Tisch-Einsätze ziemlich sauber seit Android 2.1 unter Verwendung von ContentProviderOperation zu tun, wie kaciula erwähnt.

Wenn Sie das ContentProviderOperation Objekt erstellen, können Sie .withValueBackReference (Feldname, RefNr) nennen. Wenn der Betrieb angewandt wird, unter Verwendung von applyBatch, ist das Ergebnis, dass das content Objekt, das der Einsatz () -Aufruf zugeführt wird, wird injiziert, um eine Ganzzahl hat. Die ganze Zahl wird mit dem Feldnamen String eingegeben wird, und sein Wert wird von der ContentProviderResult einer zuvor angelegten ContentProviderOperation, indiziert durch RefNr abgerufen werden.

Bitte lesen Sie das folgende Codebeispiel. In der Probe wird eine Zeile in Tabelle 1 eingefügt, und der resultierende ID (in diesem Fall „1“) wird dann als ein Wert verwendet wird, wenn die Zeile in der Tabelle 2 Der Kürze halber Einsetzen wird der Contentprovider nicht mit einer Datenbank verbunden ist. In dem Contentprovider gibt es Ausdrucke, wo es geeignet wäre, die Transaktionsabwicklung hinzuzufügen.

public class BatchTestActivity extends Activity {
    /** Called when the activity is first created. */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ArrayList<ContentProviderOperation> list = new
            ArrayList<ContentProviderOperation>();

        list.add(ContentProviderOperation.
            newInsert(BatchContentProvider.FIRST_URI).build());
        ContentValues cv = new ContentValues();
        cv.put("name", "second_name");
        cv.put("refId", 23);

        // In this example, "refId" in the contentValues will be overwritten by
        // the result from the first insert operation, indexed by 0
        list.add(ContentProviderOperation.
            newInsert(BatchContentProvider.SECOND_URI).
            withValues(cv).withValueBackReference("refId", 0).build());

        try {
            getContentResolver().applyBatch(
                BatchContentProvider.AUTHORITY, list);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        }
    }
}

public class BatchContentProvider extends ContentProvider {

    private static final String SCHEME = "content://";
    public static final String AUTHORITY = "com.test.batch";

    public static final Uri FIRST_URI =
        Uri.parse(SCHEME + AUTHORITY + "/" + "table1");
    public static final Uri SECOND_URI =
        Uri.parse(SCHEME + AUTHORITY + "/" + "table2");


    public ContentProviderResult[] applyBatch(
        ArrayList<ContentProviderOperation> operations)
            throws OperationApplicationException {
        System.out.println("starting transaction");
        ContentProviderResult[] result;
        try {
            result = super.applyBatch(operations);
        } catch (OperationApplicationException e) {
            System.out.println("aborting transaction");
            throw e;
        }
        System.out.println("ending transaction");
        return result;
    }

    public Uri insert(Uri uri, ContentValues values) {
        // this printout will have a proper value when
        // the second operation is applied
        System.out.println("" + values);

        return ContentUris.withAppendedId(uri, 1);
    }

    // other overrides omitted for brevity
}

In Ordnung - so tut dies nicht dingle planlos: der einzige Weg, ich ist, um Code und endTransaction als starttransaction URL-basierte Abfrageanforderungen denken. So etwas wie ContentResolver.query(START_TRANSACTION, null, null, null, null). Dann in ContentProvider#query auf dem registrierten URL-Aufruf basierte beginnen oder enden Transaktion

Sie können die Implementierung des Content-Provider-Objekts erhalten selbst (wenn im gleichen Prozess, Hinweis: Sie den Anbieters Prozess mit Multi-Prozess-Steuerung können = „true“ oder Prozess = „“ http://developer.android.com/guide/topics/manifest/provider-element.html ) unter Verwendung von ContentProviderClient.getLocalContentProvider (), die zu Ihrem Provider Implementierung gegossen werden können, die zusätzliche Funktionen wie ein Reset zur Verfügung stellen kann (), dass schließen und löschen die Datenbank und Sie können auch eine benutzerdefinierte Transaktion Klasseninstanz zurückgeben mit save () und close () Methoden.

public class Transaction {
    protected Transaction (SQLiteDatabase database) {
        this.database = database;
        database.beginTransaction ();
    }

    public void save () {
        this.database.setTransactionSuccessful ();
    }

    public void close () {
        this.database.endTransaction ();
    }

    private SQLiteDatabase database;
}

public Transaction createTransaction () {
    return new Transaction (this.dbHelper.getWritableDatabase ());
}

Dann:

ContentProviderClient client = getContentResolver ().acquireContentProviderClient (Contract.authorityLocal);
Transaction tx = ((LocalContentProvider) client.getLocalContentProvider ()).createTransaction ();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top