Reputation: 5985
I've run into an error about thread hierarchy. I know where the issue is, but I don't understand threads enough to understand why this is happening to me.
I have this as my basic code:
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();
}
});
Then the method for setCameraSpace()
is here. None of what it does is important to the answer, except changing the visibility of any 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();
}
}
so, I'm unsure about threads and when one is started/ended and how to put things in different places. I assume the UI elements in the setCameraSpace()
are not in a different, data-type thread because it's in a run()
?
Anyways, I'm getting this error:
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)
Upvotes: 0
Views: 69
Reputation: 25573
Looking at the documentation of Timer
(http://developer.android.com/reference/java/util/Timer.html) it appears that the Timer object has its own thread in which it executes tasks sequentially. This means that the UI is accessed from the thread owned by the Timer
, not the thread owned by the UI.
See http://developer.android.com/training/multiple-threads/communicate-ui.html for information on how to communicate with the UI when using threads.
Upvotes: 1