nki
nki

Reputation: 192

Calling from wrong thread exception

I am trying to develop an application, that uses threads to implement slideshow. I am retrieving the image path from SQLite and displaying them on the ImageView. The problem, where I got struck is, I got confused and so I am unable to understand, from which thread I am calling images() method, where I am actually implementing the slideshow.

I got the Logcat as follows -

    09-03 13:47:00.248: E/AndroidRuntime(10642): FATAL EXCEPTION: Thread-151
09-03 13:47:00.248: E/AndroidRuntime(10642): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
09-03 13:47:00.248: E/AndroidRuntime(10642):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5908)

09-03 13:47:00.248: E/AndroidRuntime(10642):    at com.example.fromstart.MainActivity.images(MainActivity.java:90)
09-03 13:47:00.248: E/AndroidRuntime(10642):    at com.example.fromstart.MainActivity$2.run(MainActivity.java:59)
09-03 13:47:00.248: E/AndroidRuntime(10642):    at java.lang.Thread.run(Thread.java:841)

MainActivity.java:

public class MainActivity extends Activity
{
    ImageView jpgView;
    TextView tv;

    //adapter mDbAdapter;   
    adapter info = new adapter(this);
    String path; 
    Handler smHandler = new Handler() 
    {
        public void handleMessage(Message msg) 
        {
            TextView myTextView = 
            (TextView)findViewById(R.id.textView1);
            myTextView.setText("Button Pressed");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        jpgView = (ImageView)findViewById(R.id.imageView1);
        tv = (TextView) findViewById(R.id.textView1);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    { 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);


        final Runnable runnable = new Runnable() 
        {
                 public void run() 
                 {
                            images();
                 }
        };
        int delay = 1000; // delay for 1 sec.
        int period = 15000; // repeat every 4 sec.
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() 
        {
            public void run() 
            {
                smHandler.post(runnable);
            }
        }, delay, period);
        Thread mythread = new Thread(runnable);
        mythread.start();
        return true;
}
        public void handleMessage(Message msg) 
        {             
            String string = "sample";
            TextView myTextView = (TextView)findViewById(R.id.textView1);
            myTextView.setText(string);
        }
        public void images()
        {
            try
            {
                 for(int i=0;i<=20;i++)
                {
                     path = info.getpath();
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                jpgView.setImageBitmap(bitmap);

                }
            }
            catch(NullPointerException er)
            {
                String ht=er.toString();
                Toast.makeText(getApplicationContext(), ht, Toast.LENGTH_LONG).show();
            }
         }
    }

I am a newbie to android, just now started working on Threads. If you find any mistakes in my code, please point out those and please suggest me, the right way to deal with this problem.

Thanks in advance.

UPDATE:

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final Handler mHandler = new Handler();

    // Create runnable for posting
    runOnUiThread(new Runnable() 
    {
        public void run() 
        {
            images();
        }
    });
    int delay = 1000; // delay for 1 sec.
    int period = 15000; // repeat every 4 sec.
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() 
    {
        public void run() 
        {
            images();
        }
    }, delay, period);




}

public void images()
{
    try
    {

    Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_LONG).show();
             path = info.getpath(); 
             Toast.makeText(getApplicationContext(), "2", Toast.LENGTH_LONG).show();
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        Toast.makeText(getApplicationContext(), "3", Toast.LENGTH_LONG).show();
        jpgView.setImageBitmap(bitmap);
        Toast.makeText(getApplicationContext(), "4", Toast.LENGTH_LONG).show();

    }
    catch(NullPointerException er) 
   {
            String ht=er.toString();
            Toast.makeText(getApplicationContext(), ht, Toast.LENGTH_LONG).show();
    }
     }

}

Upvotes: 5

Views: 6707

Answers (2)

Raghunandan
Raghunandan

Reputation: 133560

You cannot update/access ui from from a thread.

You have this

     public void run() 
     {
           images();
     }

And in images you have

    jpgView.setImageBitmap(bitmap);

You need to use runOnUiThread for updating ui.

    runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                      // do something
                    }
                });

TimerTask also runs on a different thread. So you have use a Handler for updati ui.

You can use a handler.

Edit:

Handler m_handler;
Runnable m_handlerTask ;  
m_handler = new Handler();   
m_handlerTask = new Runnable()
{
  @Override 
  public void run() { 

    // do something. call images() 
    m_handler.postDelayed(m_handlerTask, 1000);    

  }
  };
 m_handlerTask.run();

If you still wish to use a timer task use runOnUiThread

timer.scheduleAtFixedRate(new TimerTask() 
    {
        public void run() 
        {
              runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                      images();
                    }
                }); 

        }
    }, delay, period);

Upvotes: 8

Mohit
Mohit

Reputation: 11314

To update UI from any other Thread you must use

runOnUiThread(<Runnable>);

which will update your UI.

Example:

runOnUiThread(
     new Runnable()
                 { 
                  // do something on UI thread Update UI
                 });

Upvotes: 4

Related Questions