单击“浮动操作”按钮时,我的应用程序崩溃:只有创建视图层次结构的原始线程才能触及其视图

问题描述 投票:0回答:2

我正在使用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)
android crash android-room floating-action-button
2个回答
1
投票

错误消息非常明显,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;
}

0
投票

您可以在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;

    }
}
© www.soinside.com 2019 - 2024. All rights reserved.