0

I have a ListActivity with a SMS ContentObserver. The ListView displays SMS sent/received. Whenever there is change in the SMS database (sent/received), the observer calls a function within the Activity which updates the ListView.

This works ok in FROYO. But in ICS I get the following

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Please let me know what could be the issue.

The following is the top level code.

public class MyList extends ListActivity implements OnInitListener{
    @Override
    protected void onDestroy() {
        super.onDestroy();
        MyList.this.getContentResolver()
            .unregisterContentObserver(smsObserver);
    }

    @Override
    protected void onPause() {
        super.onPause();
        MyList.this.getContentResolver()
            .unregisterContentObserver(smsObserver); 
    }

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

        registerSmsEventObserver();
        updateList();
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerSmsEventObserver();
    }

    updateList() {
        //fill up the listview
    }

    private void registerSmsEventObserver() {      
        if (smsObserver != null)
            return; 

        smsObserver = new ContentObserver(null) {             
            public void onChange(boolean selfChange) {   
                updateList();
            }
        };
        MyList.this.getContentResolver().registerContentObserver(
            Uri.parse("content://sms"), true, smsObserver);
    }
}
JJD
  • 50,076
  • 60
  • 203
  • 339
user1123931
  • 479
  • 1
  • 8
  • 24
  • I tells you that you can't touch the listview from within the observer. Please send also the function called by the observer (`updateList()`) – Michał Klimczak Sep 03 '12 at 15:14

2 Answers2

3

One does not simply call updateList(); from another thread, which is ContentObserver thread. Instead, you'd better wrap it with runOnUiThread(); like

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        updateList();
    }
});
AlexN
  • 2,544
  • 16
  • 13
1

You could create the ContentObserver passing

new Handler()

This will make the onChange running on the looper of the main thread since you are creating the observer in the main thread.

JJD
  • 50,076
  • 60
  • 203
  • 339
kingston
  • 11,053
  • 14
  • 62
  • 116