scarhand
scarhand

Reputation: 4337

Only the original thread that created a view hierarchy can touch its views

I'm trying to get an ImageView to animate between 2 images in my drawable folder.

I thought everything would work fine, but the log is showing an error: Only the original thread that created a view hierarchy can touch its views.

Heres my code:

public class ExerciseActivity extends Activity {
    private ExercisesDataSource datasource;
    private Cursor cursor;
    private ImageView image_1_view;
    private Timer _timer;
    private int _index;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exercise);     

        datasource = new ExercisesDataSource(this);
        datasource.open();

        cursor = datasource.fetchExercise(exerciseDataID);

        image_1_view = (ImageView) findViewById(R.id.exercise_image);

        _index = 1;
        _timer = new Timer();
        _timer.schedule(new TickClass(), 1000);

    }

    public class TickClass extends TimerTask
    {
        private int columnIndex;

        @Override
        public void run() {
            if (_index == 1) {
                columnIndex = cursor.getColumnIndex(MySQLiteHelper.COLUMN_IMAGE_1);
                _index = 2;
            }
            else {
                columnIndex = cursor.getColumnIndex(MySQLiteHelper.COLUMN_IMAGE_2);
                _index = 1; 
            }   

            String image_1 = cursor.getString(columnIndex);
            image_1 = image_1.replace(".png", "");
            int resourceId = getResources().getIdentifier(getPackageName() + ":drawable/" + image_1, null, null);
            image_1_view.setImageDrawable(getResources().getDrawable(resourceId));
        }
    }
}

I went ahead and set the classes and functions to public but that did not fix it.

All of the resources and everything are fine, how do I fix this error?

Upvotes: 11

Views: 26067

Answers (2)

Nicklas Gnejs Eriksson
Nicklas Gnejs Eriksson

Reputation: 3415

You should use a Handler. http://developer.android.com/reference/android/os/Handler.html

Create the handler in the onCreate. Then use the handler in with the other thread. Wrap the code in within the post and this code will be executed on the UI thread which may change the UI components.

"public final boolean post (Runnable r) Added in API level 1

Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached."

    handler.post( new Runnable() {

        @Override
        public void run() {
            image_1_view.setImageDrawable(getResources().getDrawable(resourceId));
        }
    });

Upvotes: 3

Henry
Henry

Reputation: 43798

Your code in TickClass runs on another thread. To do UI work from here use runOnUiThread. See the docu for details.

runOnUiThread(new Runnable() {
    public void run() {
        image_1_view.setImageDrawable(getResources().getDrawable(resourceId));
    }
});

Upvotes: 38

Related Questions