Вставка ContentProvider ()всегда выполняется в потоке пользовательского интерфейса?

У меня есть приложение, которое должно извлекать данные с сервера и вставлять их в базу данных SQLite в ответ на ввод данных пользователем. Я думал, что это будет довольно просто -код, который извлекает данные с сервера, является довольно простым подклассом AsyncTask, и он работает именно так, как я ожидаю, без зависания потока пользовательского интерфейса. Я реализовал для него функцию обратного вызова с простым интерфейсом и обернул его в статический класс, поэтому мой код выглядит так:

MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
    @Override
    public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
        // do something with contents
    }
}

Все по-прежнему хорошо. Даже если серверу требуется час для извлечения данных, пользовательский интерфейс по-прежнему работает гладко, поскольку код в getFolderContents выполняется в методе doInBackground AsyncTask (, который находится в отдельном потоке от пользовательского интерфейса ). В самом конце метода getFolderContents вызывается onFolderContentsResponse и передается список элементов FilesystemEntry, полученных с сервера. Я действительно говорю все это только для того, чтобы, надеюсь, стало ясно, что моя проблема не в методе getFolderContents или в каком-либо моем сетевом коде, потому что он никогда не возникает там.

Проблема возникает, когда я пытаюсь вставить в базу данных через мой подкласс ContentProvider в методе onFolderContentsResponse; пользовательский интерфейс всегда зависает во время выполнения этого кода, что наводит меня на мысль, что, несмотря на вызов из метода doInBackground AsyncTask, вставки каким-то образом все еще выполняются в потоке пользовательского интерфейса. Вот как выглядит проблемный код:

MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
    @Override
    public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
        insertContentsIntoDB(contents);
    }
}

А метод insertContentsIntoDB:

void insertContentsIntoDB(final List<FilesystemEntry> contents) {
    for (FilesystemEntry entry : contents) {
        ContentValues values = new ContentValues();
        values.put(COLUMN_1, entry.attr1);
        values.put(COLUMN_2, entry.attr2);
        // etc.

        mContentResolver.insert(MyContentProvider.CONTENT_URI, values);
    }
}

где mContentResolver ранее был установлен на результат метода getContentResolver ().

Я попытался поместить insertContentsIntoDB в свой собственный поток,вот так:

MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
    @Override
    public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                insertContentsIntoDB(contents);
            }
        }).run();
    }
}

Я также пробовал запускать каждую отдельную вставку в отдельном потоке (, метод вставки в MyContentProvider синхронизирован, так что это не должно вызывать никаких проблем ):

void insertContentsIntoDB(final List<FilesystemEntry> contents) {
    for (FilesystemEntry entry : contents) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ContentValues values = new ContentValues();
                values.put(COLUMN_1, entry.attr1);
                values.put(COLUMN_2, entry.attr2);
                // etc.
                mContentResolver.insert(MyContentProvider.CONTENT_URI, values);
            }
        }).run();
    }
}

. И на всякий случай я также попробовал оба этих решения с соответствующим кодом в методе doInBackground другой AsyncTask. Наконец, я явно определил MyContentProvider как отдельный процесс в моем AndroidManifest.xml :

<provider android:name=".MyContentProvider" android:process=":remote"/>

. Он работает нормально, но по-прежнему работает в потоке пользовательского интерфейса . Это тот момент, когда я действительно начал рвать на себе волосы из-за этого, потому что это не имеет для меня никакого смысла. Что бы я ни делал, UI всегда зависает во время вставок. Есть ли способ заставить их не делать этого?

35
задан jcsmnt0 22 July 2012 в 23:44
поделиться