1

I was trying to develop a android application in which the background changes every 5 seconds I wrote code something like this :

public class BgView extends Activity implements Runnable {
    ImageView img;
    int [] setImg = {R.drawable.one,R.drawable.two};
    RelativeLayout layout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bg_view);
        layout = (RelativeLayout) findViewById(R.id.first);
        Thread t = new Thread(new BigView);
            t.start();

    }

    @Override
    public void run() {
        for (int i = 0; i < 2; ++i) {
            layout.setBackgroundResource(setImg[i]);
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

} 

It compiled fine but when i tried to run this in emulator it stopped after 5 seconds and in logcat i saw an exception which says that i cannot touch Activity class view from other function or something like that.

so i put the whole for loop inside the onCreate() method and now i don't get any exception but all i see is a blank screen for 5 seconds after that i get the last image

I know this question has been repeated but i just don't want to copy paste the code...i want to know why this happened and how can we make this working with least changes


edit : i get following exception : E/AndroidRuntime(904): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
And i want to know why putting whole for loop inside onCreate() method didn't work
Nawed Shaikh
  • 419
  • 5
  • 22

3 Answers3

2

Only UI thread can/should update the UI views, In your code you are trying to update the views directly from the new thread.

You should create a handler in your activity and then invoke that from your thread at required interval. Then handler should then update the UI. Try the code(I have not compiled the code, just typed it so ther might be typos/errors)

public class BgView extends Activity implements Runnable {
    ImageView img;
    final int [] setImg = {R.drawable.one,R.drawable.two};
    RelativeLayout layout;

    interface MyHandler {
     void letMeKnow(int i);
    }
    private MyHandler handler = new MyHandler(){

       @Override
       void letMeKnow(int i){
         layout.setBackgroundResource(setImg[i]);
       }
    }
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_bg_view);
    layout = (RelativeLayout) findViewById(R.id.first);
    Thread t = new Thread(new BigView);
        t.start();

}

@Override
public void run() {
    for (int i = 0; i < 2; ++i) {
        handler.letMeKnow(i);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

} `

gvmani
  • 1,580
  • 1
  • 12
  • 20
  • Thank you for your time(+1)...well but why was the second method not working...i mean when i put the whole for loop inside the main method(which didnt give any excpetion) i was getting black screen for 5 seconds and last image was displayed after that...can you explain this? – Nawed Shaikh Jan 31 '14 at 05:04
  • @NawedShaikh when you call Thread.Sleep from the onCreate method you are essentially making the UI thread sleep and hence the UI wont be updated. – gvmani Feb 03 '14 at 15:12
1

Put this line inside ui thread like that as you can't modify in the ui thread from another thread

runOnUiThread(new Runnable() {
    @Override
    public void run() 
    {
    layout.setBackgroundResource(setImg[i]);
    }
});

And I think that the right way to do it is using alarm . Refer to this link Android alarms

Hope this helps.

youssefhassan
  • 1,067
  • 2
  • 11
  • 17
  • Thank you for you time(+1)...i get your point but why putting for loop inside the main thread was not working..i mean i didnt get any exception but all i recieved was a blank screen for 5 seconds and then i only saw the last background? – Nawed Shaikh Jan 31 '14 at 05:00
0

Your run method should be re-written like below:

public void run() {
    for (int i = 0; i < 2; ++i) {
        runOnUiThread(new Runnable() {

            public void run() 
            {
                layout.setBackgroundResource(setImg[i]);
            }
        });

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
spgodara
  • 984
  • 9
  • 10