我有一个大问题!一些使用我的应用程序的人在执行数据库操作(如将对象更新到数据库)时,收到了ANR(应用程序没有响应),而具有数据库读取功能的(intent-)服务正在运行。
详细信息:
我在ApplicationDesgin中使用了一个单实例模式。这意味着SQLiteOpenHelper的给定上下文是ApplicationContext块操作是:
ArrayList<Workposition> web_list = (ArrayList<Workposition>) sessionDAO
.getWorkpositionDao().queryBuilder().list();
和
sessionDAO.getWorkpositionDao().update(plantevent);
两个会话都使用带有ApplicationContext的SQLLiteHelper。第一次读取操作发生在后台,第二次操作发生在onClick方法
如果你有兴趣阅读ANR,你可以去那里,但最重要的东西在上面列出。上面提到的代码行位于EventView和Workposition中。
----- pid 23262 at 2014-10-21 07:58:59 -----
Cmd line: de.myApp
JNI: CheckJNI is off; workarounds are off; pins=0; globals=293
DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0)
"main" prio=5 tid=1 WAIT
| group="main" sCount=1 dsCount=0 obj=0x41806ea0 self=0x416fcb78
| sysTid=23262 nice=0 sched=0/0 cgrp=apps handle=1073869140
| state=S schedstat=( 0 0 0 ) utm=306 stm=55 core=1
at java.lang.Object.wait(Native Method)
- waiting on <0x41806f70> (a java.lang.VMThread) held by tid=1 (main)
at java.lang.Thread.parkFor(Thread.java:1205)
at sun.misc.Unsafe.park(Unsafe.java:325)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:813)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:846)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1175)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:180)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:256)
at de.greenrobot.dao.identityscope.IdentityScopeLong.put2(IdentityScopeLong.java:85)
at de.greenrobot.dao.identityscope.IdentityScopeLong.put(IdentityScopeLong.java:76)
at de.greenrobot.dao.identityscope.IdentityScopeLong.put(IdentityScopeLong.java:31)
at de.greenrobot.dao.AbstractDao.attachEntity(AbstractDao.java:695)
at de.greenrobot.dao.AbstractDao.updateInsideSynchronized(AbstractDao.java:680)
at de.greenrobot.dao.AbstractDao.update(AbstractDao.java:654)
at de.myApp.views.EventView$1.run(EventView.java:122)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
"IntentService[a]" prio=5 tid=13 TIMED_WAIT
| group="main" sCount=1 dsCount=0 obj=0x42e28460 self=0x7b5302c0
| sysTid=23337 nice=0 sched=0/0 cgrp=apps handle=2005620856
| state=S schedstat=( 0 0 0 ) utm=7309 stm=180 core=0
at java.lang.Object.wait(Native Method)
- waiting on <0x42c4b8f8> (a java.lang.VMThread) held by tid=13 (IntentService[a])
at java.lang.Thread.parkFor(Thread.java:1205)
at sun.misc.Unsafe.park(Unsafe.java:325)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:197)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:739)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:400)
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:905)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:152)
at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:124)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:214)
at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245)
at de.greenrobot.dao.AbstractDao.loadAllFromCursor(AbstractDao.java:392)
at de.greenrobot.dao.AbstractDao.loadAllAndCloseCursor(AbstractDao.java:184)
at de.greenrobot.dao.InternalQueryDaoAccess.loadAllAndCloseCursor(InternalQueryDaoAccess.java:21)
at de.greenrobot.dao.query.Query.list(Query.java:121)
at de.greenrobot.dao.query.QueryBuilder.list(QueryBuilder.java:374)
at de.myApp.modelDAO.Workposition.upload(Workposition.java:588)
at de.myApp.service.ApiService.update(ApiService.java:138)
at de.myApp.service.ApiService.onHandleIntent(ApiService.java:51)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.os.HandlerThread.run(HandlerThread.java:61)
"Binder_3" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 obj=0x42fc7e68 self=0x778c0300
| sysTid=23306 nice=0 sched=0/0 cgrp=apps handle=2006715504
| state=S schedstat=( 0 0 0 ) utm=0 stm=0 core=1
#00 pc 0002072c /system/lib/libc.so (__ioctl+8)
#01 pc 0002cec3 /system/lib/libc.so (ioctl+14)
#02 pc 0001d3ed /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+140)
#03 pc 0001daf7 /system/lib/libbinder.so (android::IPCThreadState::getAndExecuteCommand()+6)
#04 pc 0001db8d /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+48)
#05 pc 000219e9 /system/lib/libbinder.so
#06 pc 0000ea5d /system/lib/libutils.so (android::Thread::_threadLoop(void*)+216)
#07 pc 00052299 /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+68)
#08 pc 0000e58f /system/lib/libutils.so
#09 pc 0000d278 /system/lib/libc.so (__thread_entry+72)
#10 pc 0000d410 /system/lib/libc.so (pthread_create+240)
at dalvik.system.NativeStart.run(Native Method)
"AsyncTask #1" prio=5 tid=10 WAIT
| group="main" sCount=1 dsCount=0 obj=0x42e06f38 self=0x778c2768
| sysTid=23301 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=2005674944
| state=S schedstat=( 0 0 0 ) utm=29 stm=5 core=2
at java.lang.Object.wait(Native Method)
- waiting on <0x42e070d0> (a java.lang.VMThread) held by tid=10 (AsyncTask #1)
at java.lang.Thread.parkFor(Thread.java:1205)
at sun.misc.Unsafe.park(Unsafe.java:325)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2017)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:410)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1035)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1097)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
"pool-1-thread-1" prio=5 tid=12 WAIT
| group="main" sCount=1 dsCount=0 obj=0x42ca18e0 self=0x79564280
| sysTid=23281 nice=0 sched=0/0 cgrp=apps handle=2035697368
| state=S schedstat=( 0 0 0 ) utm=1 stm=1 core=2
at java.lang.Object.wait(Native Method)
- waiting on <0x42ca1a28> (a java.lang.VMThread) held by tid=12 (pool-1-thread-1)
at java.lang.Thread.parkFor(Thread.java:1205)
at sun.misc.Unsafe.park(Unsafe.java:325)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2017)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:410)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1035)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1097)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
"Binder_2" prio=5 tid=9 NATIVE
| group="main" sCount=1 dsCount=0 obj=0x42a3f878 self=0x7255dc60
| sysTid=23273 nice=0 sched=0/0 cgrp=apps handle=1918229016
| state=S schedstat=( 0 0 0 ) utm=0 stm=0 core=0
#00 pc 0002072c /system/lib/libc.so (__ioctl+8)
#01 pc 0002cec3 /system/lib/libc.so (ioctl+14)
#02 pc 0001d3ed /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+140)
#03 pc 0001daf7 /system/lib/libbinder.so (android::IPCThreadState::getAndExecuteCommand()+6)
#04 pc 0001db8d /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+48)
#05 pc 000219e9 /system/lib/libbinder.so
#06 pc 0000ea5d /system/lib/libutils.so (android::Thread::_threadLoop(void*)+216)
#07 pc 00052299 /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+68)
#08 pc 0000e58f /system/lib/libutils.so
#09 pc 0000d278 /system/lib/libc.so (__thread_entry+72)
#10 pc 0000d410 /system/lib/libc.so (pthread_create+240)
at dalvik.system.NativeStart.run(Native Method)
我不知道为什么会出现这个问题。是因为单个实例吗?如果我使用两种不同的上下文,它会起作用吗?还是应该在后台线程中执行更新?
您永远不应该访问主线程上的数据库。许多数据库操作都使用一个锁,所以当您这样做时,任何长时间运行的后台查询都可能阻塞您的主线程。由于后台任务的优先级较低,因此很容易导致ANR。除此之外,磁盘访问可能会因任何随机原因而减慢(例如播放商店更新应用程序)。你真的不想依赖你的UI(别忘了,你的UI只有16毫秒)。
在这个ANR中,后台线程已经有Identity Scope锁,正在等待获得SqliteConnection,而您的主线程被Green Dao的Identity Scope锁阻止。没有任何内容显示数据库为什么要花这么多时间来提供连接(ANR中是否有其他未显示的线程?)。
只需确保您永远不会访问主线程上的数据库。(写或读,没多大关系)。我相信系统最终会解决这个冲突(例如,连接最终会可用)
在启用StrictMode的情况下运行应用程序,查看在UI线程上执行长时间运行的操作的位置,然后将这些操作移动到AsyncTask或其他位置。