0

I've looked around, but I'm not quite sure how this would work, and the only thread that was really close to what I'm looking for had 404'd information.

On an activity, I have four images laid out. I want them to change every 15 seconds to a different image, then I'll keep track of which image is there to let them link to another activity. I have the threads working and posting to System.out.println(), but the UI is not changing and I'm not sure how to allow it. Here's what I have so far.

public int curImage1 = 1;
public int curImage2 = 2;
public int curImage3 = 3;
public int curImage4 = 4;

onCreate() method:

// ...
imagesHandler = new Handler();
startImageSwapping();

Runnable swapImages = new Runnable() {

    @Override
    public void run() {
        handleUpdates();
        imagesHandler.postDelayed(swapImages, 3000);
    }
};

public void handleUpdates() {
    if (curImage1 == 1) {
        ((ImageView) findViewById(R.id.main_image_1)).setImageDrawable(
                getResources().getDrawable(R.drawable.logo));
        curImage1 = 5;
    }
    if (curImage1 == 5) {
        ((ImageView) findViewById(R.id.main_image_1)).setImageDrawable(
                getResources().getDrawable(R.drawable.main_image_1));
        curImage1 = 1;
    }
    System.out.println("TEST");
}

public void startImageSwapping() {
    imageThreadIsRunning = true;
    swapImages.run();
}

public void stopImageSwapping() {
    imagesHandler.removeCallbacks(swapImages);
    imageThreadIsRunning = false;
}

Current code after applying changes. Still not doing it, but want to keep this post updated for anyone else that runs into it.

Runnable swapImages = new Runnable() {

    @Override
    public void run() {
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                if (curImage1 == 1) {
                    ((ImageView) findViewById(R.id.main_image_1)).setImageDrawable(
                            getResources().getDrawable(R.drawable.logo));
                    curImage1 = 5;
                }
                if (curImage1 == 5) {
                    ((ImageView) findViewById(R.id.main_image_1)).setImageDrawable(
                            getResources().getDrawable(R.drawable.main_image_1));
                    curImage1 = 1;
                }
                System.out.println("TEST");
            }
        });
        imagesHandler.postDelayed(swapImages, 3000);
    }
};

public void startImageSwapping() {
    imageThreadIsRunning = true;
    swapImages.run();
}

public void stopImageSwapping() {
    imagesHandler.removeCallbacks(swapImages);
    imageThreadIsRunning = false;
}

@Override
protected void onDestroy() {
    stopImageSwapping();
    super.onDestroy();
}

@Override
protected void onPause() {
    stopImageSwapping();
    super.onPause();
}

@Override
protected void onStop() {
    stopImageSwapping();
    super.onStop();
}

@Override
protected void onStart() {
    if (!imageThreadIsRunning)
        startImageSwapping();
    super.onStart();
}

@Override
protected void onResume() {
    if (!imageThreadIsRunning)
        startImageSwapping();
        super.onResume();
}
Paul Ruiz
  • 2,396
  • 3
  • 27
  • 47

3 Answers3

0

If you use runOnUiThread

Runnable swapImages = new Runnable()
{
    @Override
    public void run()
    {
            runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                     handleUpdates();
                 }
            });
            imagesHandler.postDelayed(swapImages, 3000);
    }
};

Edit:

Sorry but your code quite confuse me. If I am write that from scratch I'll do it like:

public class Whatever extends Activity implements Runnable {
    ImageView iv;
    Switcher switcher;
    Thread thread;
    Handler handler = new Handler();
    public int curImage ;
    public final int curImage1 = 1;
    public final int curImage2 = 2;
    public final int curImage3 = 3;
    public final int curImage4 = 4;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        iv = (ImageView) findViewById(R.id.imageLogoDown);
        iv.setImageResourse(R.drawable.main_image_1);
            curImage = curImage1;

            switcher = new Switcher(this, handler);
        }



    /**
     * This class will implement the timer, calling run() on the UI thread each
     * time the timer elapses.
     */
    public class Switcher implements Runnable {
        private boolean _running = true;
        private Handler _handler;
        private Runnable _runnable;

        public Switcher(Runnable runnable, Handler handler) {
            _runnable = runnable;
            _handler = handler;
        }

        public void setRunning(boolean running) {
             _running = running;
        }

        @Override
        public void run() {
            while (_running) {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException ex) {
                }
                if (_running)
                    _handler.post(_runnable);
            }
        }
    }

    /**
     * Now on UI thread. Switch views.
     */
    @Override
    public void run() {
        switch (curImage) {
        case curImage1  :
            iv.setImageResourse(R.drawable.main_image_2);
            curImage = curImage2 ;
            break;
        case curImage2 :
            iv.setImageResource(R.drawable.main_image_3);
            curImage = curImage3 ;
            break;
        case curImage3 :
            iv.setImageResource(R.drawable.main_image_4);
            curImage = curImage4 ;
            break;
        case curImage4 :
            iv.setImageResource(R.drawable.main_image_1);
            curImage = curImage1 ;
            break;
        }
    }
  }

}
madlymad
  • 6,367
  • 6
  • 37
  • 68
  • OK I tried changing swapImages to that, but I put the code from handleUpdates() in the run() function. Still a no go. It'll post to the console, but not update the UI. – Paul Ruiz Mar 03 '13 at 00:29
0

Threads don't run on the UI thread so UI updates will appear to work, but not appear on the screen.

Per this Android Developer blog post and in the Android guides, you can use the runOnUiThread method or use the convenient class CountDownTimer and not have to do any threading at all:

CountDownTimer timer = new CountDownTimer(15000, // 15 second countdown
    99999) // onTick time, not used here
{

     public void onTick(long millisUntilFinished) {
         // Not used in this example
     }

     public void onFinish() {
         handleUpdates();
         timer.start(); // restarts the timer
     }
};
timer.start();
ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • Hrm, same issue here. It'll run through the println, but not update the thread. I put your code into my onCreate() function. – Paul Ruiz Mar 03 '13 at 00:41
0

Alright I actually found the answer I was looking for in one of my books - Android Recipes. Here it is for whoever might find this question later:

private Runnable timerTask = new Runnable()
{
    @Override
    public void run()
    {
        if(curImage1 == 1)
        {
            mainImage1.setImageDrawable(getResources().getDrawable(R.drawable.logo));
            curImage1 = 5;
        }
        else if(curImage1 == 5)
        {
            mainImage1.setImageDrawable(getResources().getDrawable(R.drawable.main_image_1));
            curImage1 = 1;
        }
        mHandler.postDelayed(timerTask, 3000);
    }
};

@Override
public void onResume()
{
    super.onResume();
    mHandler.post(timerTask);
}

@Override
public void onPause()
{
    super.onPause();
    mHandler.removeCallbacks(timerTask);
}
Paul Ruiz
  • 2,396
  • 3
  • 27
  • 47