单击浮动操作按钮时我的应用程序崩溃:只有创建视图层次结构的原始线程才能触摸其视图
My app crashes when i click on the Floating Action Button: Only the original thread that created a view hierarchy can touch its views
我正在使用房间数据库构建应用程序。在我的 DetailActivity 中,我设置了一个浮动操作按钮来将电影标记为收藏。当我点击 fab 时,应用程序崩溃了。
我提供了我遇到错误的方法。
public void click (){
if (isClicked) {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().removeMovie(movies.getMovieId());
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
}
});
isClicked = false;
} else {MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().addMovie(movies);
favoriteFab.setImageResource(R.drawable.heart_favorite_black);
}
});
Toast.makeText(this, "added", Toast.LENGTH_LONG).show();
isClicked = true;
}
日志:
02-13 15:30:55.294 21789-21880/? E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-1
Process: com.example.android.popularmovies2, PID: 21789
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6556)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:942)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5082)
at android.view.View.invalidateInternal(View.java:12758)
at android.view.View.invalidate(View.java:12722)
at android.view.View.invalidate(View.java:12706)
at android.widget.ImageView.setImageDrawable(ImageView.java:479)
at android.support.design.widget.FloatingActionButton.setImageDrawable(FloatingActionButton.java:483)
at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:90)
at android.support.design.widget.FloatingActionButton.setImageResource(FloatingActionButton.java:478)
at com.example.android.popularmovies2.DetailActivity.run(DetailActivity.java:152)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
可以在IO线程上进行DB操作,但不能查看相关内容。
你的这条线:
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
正在制造问题。
您只能使用来自 MainThread(UI 线程)的视图
如果你的代码在Activity,那么你可以获得方法runOnUIThread()
runOnUiThread (new Thread(new Runnable() {
public void run() {
}
}));
放在一起,
public void click() {
if (isClicked) {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().removeMovie(movies.getMovieId());
runOnUiThread(new Thread(new Runnable() {
public void run() {
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
}
}));
}
});
isClicked = false;
} else {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().addMovie(movies);
runOnUiThread(new Thread(new Runnable() {
public void run() {
favoriteFab.setImageResource(R.drawable.heart_favorite_black);
}
}));
}
});
Toast.makeText(this, "added", Toast.LENGTH_LONG).show();
isClicked = true;
}
}
该错误消息非常明显,数据库操作几乎可以保证成功,因此您只需将此行:favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
移出 runnable。
所以你的代码将是这样的:
public void click (){
if (isClicked) {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().removeMovie(movies.getMovieId());
}
});
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
isClicked = false;
} else {MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().addMovie(movies);
}
});
favoriteFab.setImageResource(R.drawable.heart_favorite_black);
Toast.makeText(this, "added", Toast.LENGTH_LONG).show();
isClicked = true;
}
我正在使用房间数据库构建应用程序。在我的 DetailActivity 中,我设置了一个浮动操作按钮来将电影标记为收藏。当我点击 fab 时,应用程序崩溃了。 我提供了我遇到错误的方法。
public void click (){
if (isClicked) {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().removeMovie(movies.getMovieId());
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
}
});
isClicked = false;
} else {MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().addMovie(movies);
favoriteFab.setImageResource(R.drawable.heart_favorite_black);
}
});
Toast.makeText(this, "added", Toast.LENGTH_LONG).show();
isClicked = true;
}
日志:
02-13 15:30:55.294 21789-21880/? E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-1
Process: com.example.android.popularmovies2, PID: 21789
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6556)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:942)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5082)
at android.view.View.invalidateInternal(View.java:12758)
at android.view.View.invalidate(View.java:12722)
at android.view.View.invalidate(View.java:12706)
at android.widget.ImageView.setImageDrawable(ImageView.java:479)
at android.support.design.widget.FloatingActionButton.setImageDrawable(FloatingActionButton.java:483)
at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:90)
at android.support.design.widget.FloatingActionButton.setImageResource(FloatingActionButton.java:478)
at com.example.android.popularmovies2.DetailActivity.run(DetailActivity.java:152)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
可以在IO线程上进行DB操作,但不能查看相关内容。
你的这条线:
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
正在制造问题。
您只能使用来自 MainThread(UI 线程)的视图
如果你的代码在Activity,那么你可以获得方法runOnUIThread()
runOnUiThread (new Thread(new Runnable() {
public void run() {
}
}));
放在一起,
public void click() {
if (isClicked) {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().removeMovie(movies.getMovieId());
runOnUiThread(new Thread(new Runnable() {
public void run() {
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
}
}));
}
});
isClicked = false;
} else {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().addMovie(movies);
runOnUiThread(new Thread(new Runnable() {
public void run() {
favoriteFab.setImageResource(R.drawable.heart_favorite_black);
}
}));
}
});
Toast.makeText(this, "added", Toast.LENGTH_LONG).show();
isClicked = true;
}
}
该错误消息非常明显,数据库操作几乎可以保证成功,因此您只需将此行:favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
移出 runnable。
所以你的代码将是这样的:
public void click (){
if (isClicked) {
MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().removeMovie(movies.getMovieId());
}
});
favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
isClicked = false;
} else {MoviesExecutor.getInstance().diskIO().execute(new Runnable() {
@Override
public void run() {
mDb.moviesDao().addMovie(movies);
}
});
favoriteFab.setImageResource(R.drawable.heart_favorite_black);
Toast.makeText(this, "added", Toast.LENGTH_LONG).show();
isClicked = true;
}