Search code examples
javaandroidrunnable

Endless loop in Runnable of ListActivity


I have a strange problem with that Runnable implementation of my Activity:

package bc.qz.client.android.activity;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import bc.qz.client.android.adapter.ScoreListAdapter;
import bc.qz.client.android.proxy.RemoteServletCaller;
import de.bc.qz.business.Score;

public class ScoreActivity extends ListActivity {

    private SharedPreferences mSharedPreferences;
    private RemoteServletCaller mRemoteServletCaller;
    private Runnable lViewScoreRunnable;
    private String mUuid;
    private String mUsername;
    private ProgressDialog mProgressDialog = null;
    private ScoreListAdapter mScoreListAdapter;
    List<Score> mAllScore = new ArrayList<Score>();

    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        mRemoteServletCaller = new RemoteServletCaller();

        mSharedPreferences = this.getSharedPreferences("de.bc.qz.client.sharedpreferences",
                Context.MODE_PRIVATE);
        mUuid = mSharedPreferences.getString("uuid", null);
        mUsername = mSharedPreferences.getString("user", null);

        mScoreListAdapter = new ScoreListAdapter(this, mAllScore);
        setListAdapter(mScoreListAdapter);

        lViewScoreRunnable = new Runnable() {
            @Override
            public void run() {
                loadAllScore(mUsername, mUuid);
            }
        };
        Thread thread = new Thread(null, lViewScoreRunnable, "MagentoBackground");
        thread.start();
        mProgressDialog = ProgressDialog.show(ScoreActivity.this, "Please wait...",
                "Retrieving data ...", true);
    }

    private void loadAllScore(String pUsername, String pUuid) {
        try {
            if (null == mUuid || mUsername == null){
                mUuid = UUID.randomUUID().toString();
                mSharedPreferences.edit().putString("uuid", mUuid).commit();
                mAllScore.addAll(mRemoteServletCaller.getAllScore(1, 10));
            }else{
                mAllScore.addAll(mRemoteServletCaller.getAllScore(mUsername, mUuid));
            }
        } catch (Exception e) {
            return;
        }
        runOnUiThread(returnRes);
    }

    private Runnable returnRes = new Runnable() {

        @Override
        public void run() {
            if (mAllScore != null && mAllScore.size() > 0) {
                mScoreListAdapter.notifyDataSetChanged();
                for (int i = 0; i < mAllScore.size(); i++)
                    mScoreListAdapter.add(mAllScore.get(i));
            }
            mProgressDialog.dismiss();
            mScoreListAdapter.notifyDataSetChanged();
        }
    };
}

when I come to the run method with my debugger, mAllScore has a size of 10. For some reason the for-loop ends in an endless loop.

I have no idear why? Please help me...


Solution

  • change

       if (mAllScore != null && mAllScore.size() > 0) {
            mScoreListAdapter.notifyDataSetChanged();
            for (int i = 0; i < mAllScore.size(); i++)
                mScoreListAdapter.add(mAllScore.get(i));
        }
    

    to

      if (mAllScore != null && mAllScore.size() > 0) {
          for(int i = 0,N=mAllScore.size();i<N;i++) {
              mScoreListAdapter.add(mAllScore.get(i));
          }
          mScoreListAdapter.notifyDataSetChanged();
      }
    

    be sure you are calling notifyDataSetChanged() in UI thread.

    and I think you are passing mAllScore to Adapter class when creating object of Adapter such as

     mAllScore = new ArrayList<String>();
     // you are adding items to this list
     // and creating adapter like 
     mScroreListAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mAllScore);
    

    so when you are adding items to the adapter using adapter.add(Object), it will add that object to mAllScore list also. (means mAllScore list got efftected)

    so when in for loop

     for(int i = 0;i<mAllScore.size();i++) { 
         mScrollAdapter.add(mAllScore.get(i)); // indirectly adding items to mAllScore
         // and thus the condition i<mAllScore.size() will never be false.