22

If I call to a ContentProvider from a Activity, which thread is ContentProvider running in?

E.g. What happens if the Activity is killed and a query is executing in the ContentProvider? Say that you have a slow network query f.ex.

louielouie
  • 14,881
  • 3
  • 26
  • 31
Torstein I. Bø
  • 1,359
  • 4
  • 14
  • 33

2 Answers2

26

If you mean the normal use case of using a ContentResolver to call a ContentProvider then here is what happens according to the best of my knowledge:

  1. I am assuming in this example that your ContentProvider lives in one process and your Activity in another process.

  2. If the ContentProvider has not been created then the onCreate() method is called using the "main" thread of the application's process.

  3. The query()/insert()/update()/delete() methods are called using BinderThreads that sit around in every application process waiting for incoming commands from other processes.

So what happens if the Activity that triggered the query()/insert()/etc is killed in the middle of one of these method calls? I can't say for certain but I'm fairly confident that whatever is happening in the ContentProvider will continue because the ContentProvider process should go on unaffected but what happens after that method returns I can't say for certain.

I'm not sure how a slow network would be involved in this at all unless your content provider is backed by a network instead of the usual sqlite db?

Clarification:

There are two possibilities when invoking a ContentProvider function (query/insert/update/delete/etc):

  1. Your ContentProvider is in the same process as the caller. If so the ContentProvider function runs synchronously on the same thread as the caller.

  2. Your ContentProvider is in a different process as the caller. If so the ContentProvider function runs on a binder thread in the ContentProvider process.

In both cases the the caller is blocked until the ContentProvider function returns. As always read the full documentation from Google and/or the AOSP source code.

http://developer.android.com/reference/android/content/ContentProvider.html http://developer.android.com/guide/topics/providers/content-provider-basics.html http://developer.android.com/guide/components/processes-and-threads.html

satur9nine
  • 13,927
  • 5
  • 80
  • 123
  • What if your Content Provider is in in the same process? – Abdullah Jibaly Dec 07 '12 at 23:14
  • It's actually no different, they query/insert/update/delete calls still happen on binder threads, just in the same process that triggered the call. They wouldn't occur on the main thread, because that could cause an ANR. – satur9nine Dec 10 '12 at 00:48
  • So triggering a resolver.delete() for example from a broadcast receiver's onReceive() method would be on the main thread, correct? – Abdullah Jibaly Dec 10 '12 at 04:07
  • Yes, there two sides, the caller and the receiver. For remote procedure calls across processes they are definitely different threads. When you call an RPC you are invoking it from whatever thread the code is running in. In the case of a broadcast receivers onReceive method that is running on the main thread. You can invoke Thread.currentThread() to find out more information about the current thread. – satur9nine Dec 10 '12 at 06:05
  • For additional details about how the threading works, refer to http://developer.android.com/guide/components/processes-and-threads.html#ThreadSafe. In particular, satur9nine's three points can be found here. – Steven Sep 24 '13 at 22:19
  • Correct me if I'm wrong here, I did a Looper.myLooper() == Looper.getMainLooper() check in insert and query of my content provider and found that the query method returns true, i.e. runs on the main thread and insert doesn't. Can anyone confirm if I'm right or wrong. Cheers! – Rahul Sainani May 23 '14 at 08:39
  • @droidster Is your ContentProvider running in the same process as your Activity? If so then calls to the ContentProvider will run on the same thread as the ContentResolver call was made. – satur9nine May 23 '14 at 16:57
  • Yep, thanks for clearing that out. I checked, my insert call from the activity is in asynctask, that's why its not on main thread. Only taking 40-50 ms for bulkinsert and query takes even less so I dont see any performance issues. Gonna keep it like this only. Thanks again. – Rahul Sainani May 23 '14 at 17:01
  • If you don't write some thing custom and smart, the ContentProvider will run on the main thread. – Matei Suica Apr 22 '15 at 07:05
5

I stumbled upon this while troubleshooting an issue where a remote process (other than UI) in the same application would continually spawn the content provider each time it ran a query. Unfortunately unless you write something custom, ContentProviders are never destroyed as long as a process is running. The content provider normally runs in the UI process thread (which was not open), so in this case of a remote process querying the contentprovider, it would spawn a new instance of the contentprovider upon each query because that separate process (UI thread) was not running at the time.

Perhaps there is a better way of doing this, but instead of spending a ton of effort rolling my own db or content provider to close the db and resources on every create, I discovered a simple workaround.

It turns out has the same ability to run in a separate process as a service does. So in my example I simply moved the content provider to the same process where the remote service was located. Problem resolved, now the content provider runs in the same process and only spawns once as long as the service is running. Also check out the android:multiprocess attribute.

Community
  • 1
  • 1
logray
  • 2,332
  • 1
  • 29
  • 30