当我尝试从数据库中获取数据时,我得到了ANR
public synchronized void insertNewObstacle(Obstacle newObstacle) {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("Insert into "+OBSTACLES_TABLE+" Values ( ' "+
newObstacle.getLongitude() + "' , ' " +
newObstacle.getLatitude() + "' , ' " +
newObstacle.getDirection() + "' , ' " +
newObstacle.getType() + "' , ' " +
newObstacle.getAddress() + "' , '" +
newObstacle.getSubmissionTime() + "' , '" +
newObstacle.getSubmitterName() + "' )"
);
db.close();
}
ANR的发生是因为我从服务器获取数据然后在本地保存 保存后(线程1)我正在尝试获取保存的数据(线程2),这就是我做的原因 方法同步。
我的问题是:
为什么它不起作用,我得到那个愚蠢的ANR消息?
或者我应该指定访问该方法的顺序吗?
1.i有asyncTaskLoader,用于从服务器获取数据并保存(线程1)。
2.asyncTask用于将数据发布到UI线程(线程2)。
跟踪文件:
at com.nilecode.matabat.AnonymousUser.DrawTypes(AnonymousUser.java:458)
at com.nilecode.matabat.AnonymousUser$MainNotificationReceiver.onReceive
(AnonymousUser.java:1085)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:763)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
"AsyncTask #3" prio=5 tid=32 WAIT
| group="main" sCount=1 dsCount=0 obj=0xa57ed5e8 self=0xb8fcd4a0
| sysTid=2608 nice=10 sched=0/0 cgrp=[fopen-error:2] handle=-1191480800
| state=S schedstat=( 21993697 71845945 80 ) utm=0 stm=1 core=0
at java.lang.Object.wait(Native Method)
- waiting on <0xa57ed700>
(a java.lang.VMThread) held by tid=32 (AsyncTask #3)
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:159)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await
(AbstractQueuedSynchronizer.java:2019)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:841)
"AsyncTask #2" prio=5 tid=29 WAIT
| group="main" sCount=1 dsCount=0 obj=0xa615bb08 self=0xb8e5b228
| sysTid=2578 nice=10 sched=0/0 cgrp=[fopen-error:2] handle=-1192800808
| state=S schedstat=( 29573221 22137266 67 ) utm=1 stm=1 core=0
at java.lang.Object.wait(Native Method)
- waiting on <0xa60b1a28> (a java.lang.VMThread) held by tid=29 (AsyncTask #2)
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:159)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await
(AbstractQueuedSynchronizer.java:2019)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:841)
"Binder_3" prio=5 tid=28 NATIVE
| group="main" sCount=1 dsCount=0 obj=0xa5144ba0 self=0xb8dd33e0
| sysTid=2574 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1194498544
| state=S schedstat=( 3711612 4635252 33 ) utm=0 stm=0 core=0
#00 pc 0002cff4
/system/lib/libc.so (__ioctl+20)
at dalvik.system.NativeStart.run(Native Method)
"RenderDrive" prio=5 tid=27 SUSPENDED
| group="main" sCount=1 dsCount=0 obj=0xa52ffd40 self=0xb8cf1eb0
| sysTid=2559 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1194081904
| state=S schedstat=( 278861639 194938487 3193 ) utm=0 stm=27 core=1
#00 pc 0002ed67
/system/lib/libc.so (__futex_syscall4+23)
at java.lang.VMThread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1013)
at java.lang.Thread.sleep(Thread.java:995)
at maps.p.b.c((null):-1)
at maps.an.b.run((null):-1)
"IntentService[Request New Dataset Service]" prio=5 tid=26 SUSPENDED
| group="main" sCount=1 dsCount=0 obj=0xa60b9148 self=0xb8cce168
| sysTid=2557 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1194331408
| state=S schedstat=( 22023302408 4429908617 55349 ) utm=209 stm=1992 core=0
#00 pc 0002ed67
/system/lib/libc.so (__futex_syscall4+23)
at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:734)
at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1603)
at com.nilecode.matabat.data.LocalCachedObstacles.insertNewObstacle(LocalCachedObstacles.java:74)
at com.nilecode.matabat.data.LocalCachedObstacles.insertNewDataSet(LocalCachedObstacles.java:62)
at com.nilecode.matabat.ServerAsyncLoader.loadInBackground(ServerAsyncLoader.java:162)
at com.nilecode.matabat.RequestNewDataSetService.requestAndCacheNearByLocations
(RequestNewDataSetService.java:134)
答案 0 :(得分:2)
synchronized
方法锁定对象本身。如果另一个线程持有该锁,例如通过运行同一对象的其他同步方法,您的调用将阻塞,直到锁定可用。
阻止主UI线程5秒或更长时间会导致ANR。
不需要与sqlite同步 - 数据库将处理它自己的锁定。但是,独占写入事务将阻止SQLITE_BUSY
错误的任何其他访问。
通常,如果只有一个线程正在访问它,sqlite的效果最好。你应该重新考虑你的设计。如果有一个长时间运行的数据库操作不需要是原子操作,请将其拆分为较短的部分。
答案 1 :(得分:0)
当UI线程的响应时间超过5秒时,会显示ANR消息(因设备而异)。我认为你是从UI线程调用方法,它在与你调用insertNewObstacle
方法的对象相同的对象上同步。
另外,为什么你使用两个单独的线程进行写作和阅读?只需使用一个AsyncTask
,它将从网络获取数据并在doInBackground
的UI线程中显示数据。
答案 2 :(得分:0)
ANR (Activity Not Responding)
来到ui胎面时不会在5秒钟内收到任何响应。从服务器获取数据并将其保存到数据库可以通过线程后台服务或仅使用服务来完成,为什么我建议后台服务,以便ui线程可以轻松运行。更多的是从数据库加载数据,我认为你不需要异步任务。
为什么你得到ANR?
所以ans是你使用两个异步任务,两个都是ui线程阻止器,一个依赖于其他。因此,除非您没有从服务器加载数据并将其保存到数据库中,否则您需要再次向ui异步任务加载数据。所以ui线程必须等待,直到它将数据从服务器和数据加载到ui。异步任务有不同的用例不要在这里使用它并且tru以避免同步块unnessasary。