我正在使用Room Database构建应用程序。在我的DetailActivity中,我设置了一个浮动动作按钮,将电影标记为收藏。当我点击工厂时,应用程序崩溃了。我提供了我遇到错误的方法。
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$4.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)
错误消息非常明显,DB操作几乎可以保证成功,所以你可以移动这一行:favoriteFab.setImageResource(R.drawable.heart_favorite_border_black);
out the 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;
}
您可以在IO线程上执行数据库操作,但不能查看相关的东西。
你的这一行:
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;
}
}