I just started a new job and am working on an app that requires passing large data sets around the application. Currently the app uses persistent storage and is constantly querying a SQL database to fetch and display these large data sets to the user. Because of all of these expensive operations the app has become almost unusable (too many loading spinners for operations that take too long). My solution is to load the data when the main activity is launched and then pass it as needed to any new activities.
I implemented the first stage of this change with one data set. However, when I tried to pass the ArrayList with all this data in the intent's extras bundle I got the following error:
04-27 06:42:32.022: E/AndroidRuntime(14180): FATAL EXCEPTION: main
04-27 06:42:32.022: E/AndroidRuntime(14180): Process: com.myprocess, PID: 14180
04-27 06:42:32.022: E/AndroidRuntime(14180): java.lang.SecurityException: Unable to find app for caller android.app.ApplicationThreadProxy@42b32678 (pid=14180) when publishing content providers
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.os.Parcel.readException(Parcel.java:1472)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.os.Parcel.readException(Parcel.java:1426)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.app.ActivityManagerProxy.publishContentProviders(ActivityManagerNative.java:2977)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.app.ActivityThread.installContentProviders(ActivityThread.java:4591)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4522)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.app.ActivityThread.access$1500(ActivityThread.java:151)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1381)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.os.Handler.dispatchMessage(Handler.java:110)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.os.Looper.loop(Looper.java:193)
04-27 06:42:32.022: E/AndroidRuntime(14180): at android.app.ActivityThread.main(ActivityThread.java:5292)
04-27 06:42:32.022: E/AndroidRuntime(14180): at java.lang.reflect.Method.invokeNative(Native Method)
04-27 06:42:32.022: E/AndroidRuntime(14180): at java.lang.reflect.Method.invoke(Method.java:515)
04-27 06:42:32.022: E/AndroidRuntime(14180): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
04-27 06:42:32.022: E/AndroidRuntime(14180): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
04-27 06:42:32.022: E/AndroidRuntime(14180): at dalvik.system.NativeStart.main(Native Method)
Which, based on this stackoverflow post: Using Crop intent Getting java.lang.SecurityException: Unable to find app for caller android.app.ApplicationThreadProxy@4266ae80 as well as testing with smaller data-sets I figured out was (almost certainly) being caused by sending too much data via the intent extras bundle.
I have two questions.
- First, does my assessment sound correct? I haven't been able to find anything from the last four years that explicitly states that the extras bundle has a size limit (there's lots from 2012 and before though).
- Assuming I'm correct, I'm planning on using a singleton to store data sets that are too big to be passed as an intent, and then implementing the necessary checks to ensure that it works with the activity life cycle (re-load the from the database if the activity is destroyed and I loose the data). Any other suggestions? I know this isn't exactly best practice but I can't think of a better way to do it.
I should also mention that because of the usability requirements for the app loading the data incrementally isn't an option.