ContentProvider的插入()始终运行UI线程? [英] ContentProvider insert() always runs on UI thread?

查看:213
本文介绍了ContentProvider的插入()始终运行UI线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序需要从服务器获取数据并将其插入到一个SQLite数据库,响应用户的输入。我想这将是pretty的简单 - code,拉数据从服务器是AsyncTask的一个相当简单的子类,它的工作原理完全按照我期望它不挂在UI线程。我实现的回调功能,它用一个简单的界面,包裹在一个静态类,所以我的code是这样的:

I have an app that needs to pull data from a server and insert it into an SQLite database in response to user input. I thought this would be pretty simple - the code that pulls the data from the server is a fairly straightforward subclass of AsyncTask, and it works exactly as I expect it to without hanging the UI thread. I implemented callback functionality for it with a simple interface and wrapped it in a static class, so my code looks like this:

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

所有还是不错的。即使服务器需要一个小时来检索数据时,UI仍然运行平稳,因为$ C $中的c getFolderContents在一个AsyncTask的(这是在一个单独的线程从UI)的doInBackground方法运行。在getFolderContents方法的最末端,所述onFolderContentsResponse将被调用并且从服务器被接收FilesystemEntry的列表。我只是真的说这一切都使得它的希望显然,我的问题是不是在getFolderContents方法或我的任何联网code,因为它不会永远出现在那里。

All still good. Even if the server takes an hour to retrieve the data, the UI still runs smoothly, because the code in getFolderContents is running in the doInBackground method of an AsyncTask (which is in a separate thread from the UI). At the very end of the getFolderContents method, the onFolderContentsResponse is called and passed the list of FilesystemEntry's that was received from the server. I only really say all this so that it's hopefully clear that my problem is not in the getFolderContents method or in any of my networking code, because it doesn't ever occur there.

在问题出现时,我尝试插入到通过我的onFolderContentsResponse方法中的子类ContentProvider的数据库;用户界面始终而code正在执行,导致我认为,尽管从的AsyncTask的doInBackground方法被调用时,刀片在某种程度上仍然在UI线程上运行挂起。下面是有问题的code是这样的:

The problem arises when I try to insert into a database via my subclass of ContentProvider within the onFolderContentsResponse method; the UI always hangs while that code is executing, leading me to believe that despite being called from the doInBackground method of an AsyncTask, the inserts are somehow still running on the UI thread. Here's what the problematic code looks like:

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一直previously设置到getContentResolver()方法的结果。

where mContentResolver has been previously set to the result of the getContentResolver() method.

我试图把insertContentsIntoDB在自己的线程,就像这样:

I've tried putting insertContentsIntoDB in its own Thread, like so:

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插入方法是同步的,所以这应该不会造成有任何问题):

I've also tried running each individual insert in its own thread (the insert method in MyContentProvider is synchronized, so this shouldn't cause any issues there):

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();
    }
}

和刚才的好办法,我也试着这两个解决方案与相关code在另一个的AsyncTask的doInBackground方法的。最后,我已经明确定义MyContentProvider作为生活在一个单独的进程在我的Andr​​oidManifest.xml:

And just for good measure, I've also tried both of those solutions with the relevant code in the doInBackground method of another AsyncTask. Finally, I've explicitly defined MyContentProvider as living in a separate process in my AndroidManifest.xml:

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

运行良好,但它的似乎仍然在UI线程运行。这就是我真正开始撕扯我的头发,在这一点,因为这没有任何意义了我的全部。无论我做什么,用户界面​​在插入总是挂起。有没有什么办法让他们不要?

It runs fine, but it still seems to run in the UI thread. That's the point where I really started tearing my hair out over this, because that doesn't make any sense at all to me. No matter what I do, the UI always hangs during the inserts. Is there any way to get them not to?

推荐答案

而不是调用的 mContentResolver.insert(),使用<一个href="http://developer.android.com/reference/android/content/AsyncQueryHandler.html"><$c$c>AsyncQueryHandler和它的<一个href="http://developer.android.com/reference/android/content/AsyncQueryHandler.html#startInsert%28int,%20java.lang.Object,%20android.net.Uri,%20android.content.ContentValues%29"><$c$c>startInsert()方法。 AsyncQueryHandler 旨在促进异步 ContentResolver的查询。

Instead of calling mContentResolver.insert(), use AsyncQueryHandler and its startInsert() method. AsyncQueryHandler is designed to facilitate asynchronous ContentResolver queries.

这篇关于ContentProvider的插入()始终运行UI线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆