Android致命异常线程层次结构(请解释)

时间:2016-04-11 19:36:41

标签: java android multithreading

我遇到了有关线程层次结构的错误。我知道问题出在哪里,但我不明白线程足以理解为什么会发生这种情况。

我将此作为我的基本代码:

public class CameraPage extends Activity implements ImageSaver.OnImageSavedListener {
    public int numPics = 0;
    public Timer gifTimer;

    protected void onCreate(Bundle savedInstanceState) {
        gif_button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                countdownTimer = new CountDownTimer((seconds * 1000 + 500), 1000) {
                public void onTick(long millisUntilFinished) {
                    // Do things
                }
                public void onFinish() {
                    numPics = 0;
                    gifTimer = new Timer();
                    gifTimer.scheduleAtFixedRate(new TimerTask(){
                        @Override
                        public void run(){
                            numPics++;
                            if(numPics <= 5) {
                                Log.d("********", "Take a picture " + numPics);
                            } else {
                                gifTimer.cancel();
                                Log.d("********", "No More Pictures " + numPics);
                                setCameraSpace();
                            }
                        }
                    },0,500);
                }
            }.start();
         }  
    });

然后setCameraSpace()的方法就在这里。除了改变任何View的可见性之外,它的作用都不重要。

public void setCameraSpace(){
    Log.d("***********", "Finish " + bitmapArray);

    if (icon_alert_int == 1) {
        icon_alert.setVisibility(View.VISIBLE);
    } else {
        icon_alert.setVisibility(View.GONE);
    }
    if(gallery){
        gallery_button.setVisibility(View.VISIBLE);
    } else {
        gallery_button.setVisibility(View.GONE);
    }
    camera_preview_container.setVisibility(View.GONE);
    countdown_timer.setVisibility(View.GONE);
    picture_button.setVisibility(View.VISIBLE);
    back_button.setVisibility(View.VISIBLE);
    front_flash.setVisibility(View.GONE);
    front_flash.setAlpha(0f);
    countdown_timer.setText("");
    camera_text.setText(pref_session_start_inp);

    if (pref_session_auto_live_view) {
        //Countdown until Live view reappears
        live_view_timer = new CountDownTimer((pref_session_auto_live_view_inp * 1000 + 50), 1000) {
            public void onTick(long millisUntilFinished) {
                auto_live_view_text.setText("" + ((millisUntilFinished / 1000) - 1));
            }

            public void onFinish() {
                latest_picture_container.setVisibility(View.GONE);
                camera_preview_container.setVisibility(View.VISIBLE);
                auto_live_view_text.setText(String.valueOf(pref_session_auto_live_view_inp));
                camera_text.setText(pref_session_start_inp);
            }
        }.start();
    }
}

所以,我不确定线程​​以及何时开始/结束以及如何将东西放在不同的地方。我假设setCameraSpace()中的UI元素不属于不同的数据类型线程,因为它位于run()

无论如何,我收到了这个错误:

FATAL EXCEPTION: Timer-0
Process: com.cleanercoding.cleanerphotobooth, PID: 14355
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7647)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1107)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5029)
at android.view.View.invalidateInternal(View.java:12953)
at android.view.View.invalidate(View.java:12917)
at android.view.View.setFlags(View.java:10850)
at android.view.View.setVisibility(View.java:7233)
at android.widget.ImageView.setVisibility(ImageView.java:1420)
at com.cleanercoding.cleanerphotobooth.CameraPage.setCameraSpace(CameraPage.java:1263)
at com.cleanercoding.cleanerphotobooth.CameraPage$6$2$1.run(CameraPage.java:552)
at java.util.Timer$TimerImpl.run(Timer.java:284)

1 个答案:

答案 0 :(得分:1)

查看Timerhttp://developer.android.com/reference/java/util/Timer.html)的文档,看来Timer对象有自己的线程,在该线程中,它按顺序执行任务。这意味着可以从Timer拥有的线程访问UI,而不是UI拥有的线程。

有关使用线程时如何与UI通信的信息,请参阅http://developer.android.com/training/multiple-threads/communicate-ui.html