Pradyut Bhattacharya
Pradyut Bhattacharya

Reputation: 5748

Update CustomArrayAdapter after AsyncTask in Android

I m having a CustomArrayAdapter which I m using to update a a custom ListView.

This is working fine but when I m trying to update the view after getting results in AsyncView onPostExecute using notifyDataSetChanged it is not updating nor it is returning any exceptions.

The code for onCreate -

public class MainActivity extends ListActivity {
    String[] presidents = {"Dwight D. Eisenhower","John F. Kennedy","Lyndon B. Johnson","Richard Nixon","Gerald Ford","Jimmy Carter","Ronald Reagan","George H. W. Bush","Bill Clinton","George W. Bush","Barack Obama"};
    String[] pics = {"5237","5438", "184", "184", "184", "184", "184", "184", "184", "184", "184", "184"};
    private String[] names;
    private String[] pid;   
    ListActivity obj;   
    CustomArrayAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
        obj = this;     
        try {
            adapter =new CustomArrayAdapter(obj, presidents, pics);
            setListAdapter(adapter);            
            new DownloadTextTask().execute("http://nvoids.com/rest/hello/users/");          
        } catch(Exception e) {
            Log.d("Listview1", "Exception: " + e.getLocalizedMessage());
        }

    }

The AsyncTask's onPostExecute -

protected void onPostExecute(String result) {

  Toast.makeText(getBaseContext(), result.substring(1, 10) ,Toast.LENGTH_SHORT).show();         
  try 
    {               
        JSONArray jarr = new JSONArray(result);
         names = new String[jarr.length() -1];
         pid = new String[jarr.length() -1];
         for (int i =0; i< jarr.length(); i++) {
                JSONObject jObj = new JSONObject(jarr.get(i).toString());
                names[i] = jObj.getString("value");                 
                pid[i] = jObj.getString("pid");                 
            }
            super.onPostExecute(result);
            adapter =new CustomArrayAdapter(obj, names, pid);
            adapter.notifyDataSetChanged();
        } catch(Exception e) {
            Log.d("ListView1", "after getting string: " + e.getLocalizedMessage());
        }
    } 

By the way the CustomArrayAdapter class if required -

public class CustomArrayAdapter extends ArrayAdapter<String> {
private final Activity context;    
private final String[] presidents;    
private final String[] imageIds;

 public CustomArrayAdapter(Activity context,String[] presidents, String[] imageIds) {
    super(context, R.layout.lvrowlayout, presidents);
     this.context = context;
     this.presidents = presidents;
     this.imageIds = imageIds;
 }

 @Override    
 public View getView(int position, View view, ViewGroup parent) {
     //---print the index of the row to examine---        
     Log.d("Listview1",String.valueOf(position));

    LayoutInflater inflater = context.getLayoutInflater();
    View rowView= inflater.inflate(R.layout.lvrowlayout, null, true);

    TextView txtTitle = (TextView) rowView.findViewById(R.id.txtPresidentName);
    ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);

    txtTitle.setText(presidents[position]);

    //imageView.setImageResource(imageIds[position]);

    new DownloadImageTask((ImageView)  imageView )
    .execute("http://nvoids.com/dir/image_" + imageIds[position] + ".jpeg");


    return rowView;

 }

 private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

        public DownloadImageTask(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {
            String urldisplay = urls[0];
            Log.d("CustomArrayGetImage Error", urldisplay);
            Bitmap mIcon11 = null;
            try {
                InputStream in = new java.net.URL(urldisplay).openStream();
                mIcon11 = BitmapFactory.decodeStream(in);
            } catch (Exception e) {
                Log.d("CustomArrayGetImage Error", e.getMessage());
                e.printStackTrace();
            }
            return mIcon11;
        }

        protected void onPostExecute(Bitmap result) {
            bmImage.setImageBitmap(result);
        }
    }    
 }

EDIT -

As in the answers passing the parameters also does not work -

  try {
        adapter =new CustomArrayAdapter(obj, presidents, pics);         
        setListAdapter(adapter);            
        new DownloadTextTask(adapter).execute( "http://nvoids.com/rest/hello/users/");          
    } catch(Exception e) {
        Log.d("Listview1", "Exception: " + e.getLocalizedMessage());
    }

In the DownloadAsyncTask -

   private class DownloadTextTask extends AsyncTask<String, Void, String> {
    CustomArrayAdapter ca;

    public DownloadTextTask(CustomArrayAdapter ca) {
        this.ca = ca;
    }

 ......

  protected void onPostExecute(String result) {
        //Toast.makeText(getBaseContext(), result, Toast.LENGTH_LONG).show();
        Toast.makeText(getBaseContext(), result.substring(1, 10) ,Toast.LENGTH_SHORT).show();           
        try 
        {               
            JSONArray jarr = new JSONArray(result);
            names = new String[jarr.length() -1];
            pid = new String[jarr.length() -1];
            for (int i =0; i< jarr.length(); i++) {
                JSONObject jObj = new JSONObject(jarr.get(i).toString());
                names[i] = jObj.getString("value");                 
                pid[i] = jObj.getString("pid");
                ca.addAll(names[i] , pid[i]);
            }
            /*
            super.onPostExecute(result);                
            adapter =new CustomArrayAdapter(obj, names, pid);               
            lv.setAdapter(adapter);             
            obj.setListAdapter(adapter);
            */

            ca.notifyDataSetChanged();
        } catch(Exception e) {
            Log.d("ListView1", "after getting string: " + e.getLocalizedMessage());
        }
    }

Upvotes: 1

Views: 99

Answers (2)

dilix
dilix

Reputation: 3893

adapter =new CustomArrayAdapter(obj, names, pid);
adapter.notifyDataSetChanged();

notifyDataSetChange notify observers to update data.

So in your example you notify new adapter to update their data, but you don't attach adapter to your list.

But create each time new adapter - is not a good practise, you have to update data in your adapter (in your case list of presidents) and then call notifyDataSetChange on your existing adapter.

PS ArrayAdapter already have a list under it and you can call add and don't need to store list of presidents. In your case i think it's better to create

class PresidentsWrapper { String name, String photoUrl }

And create ArrayAdapter<PresidentWrapper>

In this case you don't need any underlying structures and can do like this:

getItem(position);
add(new PresidentWrapper(...));

Upvotes: 0

user370305
user370305

Reputation: 109237

Because, You are creating new object of Custom Adapter in AsyncTask's onPostExecute()

Like,

adapter =new CustomArrayAdapter(obj, names, pid);
adapter.notifyDataSetChanged();

Which is not set to ListView. So either write syntax for setListAdapter() to ListView in onPostExecute() (For this you need ListView reference in AsyncTask) or Use the same object which you have created in onCreate() of Your ListActivity, Pass that adapter object in Constructor of AsyncTask and use Object in onPostExecute().

Upvotes: 1

Related Questions