我需要在游戏活动的onCreate()
方法中执行一些初始处理。我编写了以下内容以尝试从UI线程执行该处理:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
parentGrid = (ArrowGridLayout) findViewById(R.id.arrowPlainGrid);
//populates the game board without blocking UI thread.
new Thread(new Runnable() {
@Override
public void run() {
final LevelFunction someLevel = new LevelFunction(parentGrid.getContext(), numRows, numCols, parentGrid, generateCardList(numRows, numCols), true);
PlainArrowTest.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "Look at me populating the level on a background thread!");
someLevel.populateGridCards();
}
});
}
}).start();
每次我在#34;普通"中运行应用程序(使用Android Studio)时,这似乎都很好用。模式,但如果我在调试模式下运行它,Activity
不会加载,因为它说我试图操纵UI线程之外的UI对象(或多或少)。
我希望能够调试我的应用程序,而无需评论此代码。有没有人碰到这个?有没有办法可以改变我的代码以防止在调试中发生这种情况?
这是我的logcat输出:
05-23 00:21:52.792 2127-2127/bwg.arrow I/art﹕ Not late-enabling -Xcheck:jni (already on)
05-23 00:21:52.955 2127-2127/bwg.arrow W/ActivityThread﹕ Application bwg.arrow is waiting for the debugger on port 8100...
05-23 00:21:52.964 2127-2127/bwg.arrow I/System.out﹕ Sending WAIT chunk
05-23 00:21:52.975 2127-2134/bwg.arrow I/art﹕ Debugger is active
05-23 00:21:53.184 2127-2127/bwg.arrow I/System.out﹕ Debugger has connected
05-23 00:22:13.540 2127-2518/bwg.arrow I/GameLoop -﹕ Started run()...
05-23 00:22:13.541 2127-2518/bwg.arrow I/GameLoop -﹕ Nap time! Sleeping for 16 ms.
05-23 00:22:13.567 2127-2237/bwg.arrow W/EGL_emulation﹕ eglSurfaceAttrib not implemented
05-23 00:22:13.567 2127-2237/bwg.arrow W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa5d582a0, error=EGL_SUCCESS
05-23 00:22:13.670 2127-2518/bwg.arrow I/GameLoop -﹕ Nap time! Sleeping for 15 ms.
05-23 00:22:13.730 2127-2134/bwg.arrow W/art﹕ Suspending all threads took: 24.584ms
--------- beginning of crash
05-23 00:22:13.734 2127-2517/bwg.arrow E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-120
Process: bwg.arrow, PID: 2127
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6247)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:867)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
at android.view.View.requestLayout(View.java:17364)
at android.widget.GridLayout.requestLayout(GridLayout.java:1092)
at android.widget.GridLayout.setRowCount(GridLayout.java:392)
at bwg.arrow.LevelFunction.<init>(LevelFunction.java:54)
at bwg.arrow.PlainArrowTest$1.run(PlainArrowTest.java:57)
at java.lang.Thread.run(Thread.java:818)
05-23 00:22:13.841 2127-2139/bwg.arrow I/art﹕ Background sticky concurrent mark sweep GC freed 5497(318KB) AllocSpace objects, 0(0B) LOS objects, 36% free, 726KB/1135KB, paused 98.378ms total 194.327ms
05-23 00:22:13.890 2127-2518/bwg.arrow I/GameLoop -﹕ Nap time! Sleeping for 16 ms.
05-23 00:22:14.001 2127-2518/bwg.arrow I/GameLoop -﹕ Nap time! Sleeping for 16 ms.
05-23 00:22:14.065 2127-2518/bwg.arrow I/GameLoop -﹕ Nap time! Sleeping for 16 ms.
05-23 00:22:14.126 2127-2127/bwg.arrow I/PlainArrowTest﹕ Oh look at that! I paused the background thread. You're welcome.
05-23 00:22:15.711 2127-2127/bwg.arrow I/PlainArrowTest﹕ Oh look at that! I stopped the background thread. You're welcome.
05-23 00:22:15.711 2127-2127/bwg.arrow I/PlainArrowTest﹕ Oh look at that! I destroyed the background thread. You're welcome.
05-23 00:27:13.929 2127-2517/bwg.arrow I/Process﹕ Sending signal. PID: 2127 SIG: 9
答案 0 :(得分:0)
是的,你正在后台线程中操纵UI对象,这就是在寻找麻烦。
查看logcat输出中的堆栈跟踪:
[...]
at android.view.View.requestLayout(View.java:17364)
at android.widget.GridLayout.setRowCount(GridLayout.java:392)
at bwg.arrow.LevelFunction.<init>(LevelFunction.java:54)
at bwg.arrow.PlainArrowTest$1.run(PlainArrowTest.java:57)
at java.lang.Thread.run(Thread.java:818)
这表示在后台线程上运行的LevelFunction
调用GridLayout.setRowCount()
(然后它会尝试执行布局)。
你不能这样做。您应该运行在UI线程上操作视图的所有代码 这里的解决方案是删除你的额外线程(正如Bojan Kseneman在评论中指出的那样)。
至于debug和release(&#34; normal&#34;)版本之间的区别:debug用于调试,除其他外,它意味着在程序中运行更多的健全性检查。
线程的问题出现在所有类型的构建中,但是调试版本能够及早检测到它并抛出异常以告知您问题所在。