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

У меня есть приложение, которое должно получить данные с сервера и вставить их в базу данных 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; Пользовательский интерфейс всегда зависает во время выполнения этого кода, что заставляет меня поверить, что, несмотря на то, что метод AsIncTask вызывается из метода doInBackground, операции вставки все равно выполняются в потоке пользовательского интерфейса. Вот как выглядит проблемный код:

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"/>

Работает нормально, но этоstill seems to run in the UI thread, Это тот момент, когда я действительно начал рвать на себе волосы из-за этого, потому что это не имеет никакого смысла для меня. Независимо от того, что я делаю, пользовательский интерфейс всегда зависает во время вставки. Есть ли способ заставить их не делать этого?

Ответы на вопрос(4)

Ваш ответ на вопрос