2

I am receiving data from network in a separate thread (which is in some other class, here the whole problem is, but I can't put the receiving code in activity class due to inherent complexity of the legacy code) and I want to update the ListView as the data is received (realtime).. For that I have created a ListView, ArratAdapter and an ArrayList variavles... Following is the some relevant code

public class LogInSuccessActivity extends Activity {
    private String LOG_TAG = "LogInSuccessActivity";
    private TextView welcomeTxtLbl = null;
    private ListView buddyListView = null;
    private ArrayAdapter<Buddy> buddyListAdapter = null;
    // BuddyList
    private ArrayList<Buddy> buddyList = null;


    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loginsuccess);
        // get the TextView and ListView
        welcomeTxtLbl = (TextView) findViewById(R.id.loginsuceeslbl);
        buddyListView = (ListView) findViewById(R.id.buddylistview);

        String uname = getIntent().getStringExtra("username");
        if (uname != null) {
            welcomeTxtLbl.setText("Welcome " + uname + ", Greetings!!");
        } else {
            welcomeTxtLbl.setText("SignIn successfull !!");
        }
        buddyList = new ArrayList<Buddy>();
        buddyListAdapter = new ArrayAdapter<Buddy>(this,
                android.R.layout.simple_list_item_1, buddyList);
        buddyListView.setAdapter(buddyListAdapter);

        // persist the context
        ReceiverThread.loginSuccessActi = LogInSuccessActivity.this;
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onResume()
     * 
     * @Override protected void onStart() { // TODO Auto-generated method stub
     * super.onStart();
     * 
     * }
     */

    @Override
    protected void onStop() {
        super.onStop();
        Log.e(LOG_TAG, "onStop is called ");
        buddyListAdapter.clear();
        buddyList.clear();

    }

    public void addBuddy(Buddy buddy) {
        buddyList.add(buddy);
        buddyListAdapter.notifyDataSetChanged();
    }

    Runnable updateTheListView = new Runnable() {
        @Override
        public void run() {
            // synchronized (buddyList) {
            buddyListAdapter.notifyDataSetChanged();

            // }
        }
    };

    public void refreshTheListView(Buddy buddy) {
        System.out.println("Refreshing the ListView list size is : "
                + buddyList.size());
        buddyList.add(buddy);
        // buddyListAdapter.add(buddy);
        // buddyListView.post(updateTheListView);
        this.runOnUiThread(updateTheListView);
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onDestroy()
     */
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        Log.e(LOG_TAG, "onDestroy is called ");
        super.onDestroy();
        buddyList = null;
        buddyListAdapter = null;
        buddyListView = null;
        ReceiverThread.loginSuccessActi = null;
    }

}

Now from the thread I call the method addBuddy() whenever new Buddy is received...Which is a static method since Receiver Thread is in a different class...

The code however is not working, Please give me suggestions to improve this code. I know its not good but I dont know how to fix it due to my lack of knowledge in andoid prorgamming. I also read somewhere about DataSetObserver can they be used in my case.. I am a newbie in android arena so please excuse me for my lack of basic concepts.... Thanks,

EDIT One thing I forgot to mention is that I am not updating the UI from a separate thread (I know I can't), What I do is whenever Somedata (for simplicity of the question of course I do all the filtering ) arrives I call the addBuddy()...

Now on the UI thread I will call the notifyDataSetChanged() method of the ArrayAdapter to carry on the view updation.

EDIT 2 Following is the code in another thread from where I receive data..

    if (loginSuccessActi != null) {
                        loginSuccessActi.refreshTheListView(new Buddy(values));
//                      loginSuccessActi.addBuddy(new Buddy(values));
                    }

and I get following error The content of the adapter has changed but ListView did not receive a notification.

Amit
  • 13,134
  • 17
  • 77
  • 148
  • I think you will need to show more of your code in order to get a more specific diagnosis of your problem. Can you at least show the code that accepts new data and calls `addBuddy`. – Louth May 09 '12 at 20:56
  • please see the edit, I have changed the code.... – Amit May 10 '12 at 06:03

2 Answers2

1

You should read up on Processes and Threads on the android developer site.

Even though you are doing the work on a separate thread, you can't access the UI thread from another process.

One way around this would be to implement an AsyncTask to do the work and then update your adapter via the onPostExecute method.

Louth
  • 11,401
  • 5
  • 28
  • 37
0

After reading almost all the similar questions on SO, I finally solved it by using following steps:-

  1. Fixed the few design issues in the thread which was calling the addBuddy() method,
  2. Changed my addBuddy method to

    public void addBuddy(final Buddy buddy) {

        Log.i(LOG_TAG, " ADDING BUDDY + " + buddy);
        buddyListView.post(// UI thread ;
                new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        synchronized (buddyList) {
                            buddyList.add(buddy);
                            buddyListAdapter.notifyDataSetChanged();
                        }
                        // buddyListAdapter.add(buddy);
                    }
                });
    }
    

I have also changed the OverAll design of the application , as I got wiser while searching the answer of this problem. Now I share data using Singelton Class and Static variables. Following links can be useful if someone else has similar problem in future.

Painless Threading

Singleton Class

Using Threads

For those, who have similar problem best advice is to "Trust Yourself, You can do it."

Community
  • 1
  • 1
Amit
  • 13,134
  • 17
  • 77
  • 148