2

I am using following code as Cusotm Array adapter of a ListView in android

In View new MyAsyncTask(url, callback); will be run again and again, How can i make it so that the query to the server will be performed only once.

@Override
        public View getView(int position, View convertView, ViewGroup parent) 
        {       
            final Question question = quesions.get(position);
            final OpenionUser myUser = question.getUser();

            View view = convertView;
            ViewHolder viewHolder = new ViewHolder();

            if (convertView == null)
            {
                view = inflator.inflate(R.layout.question_adapter_layout, parent, false);

                viewHolder.firstPhotoPercent  = (TextView) view.findViewById(R.id.firstPhotoProgressText);
                viewHolder.secondPhotoPercent = (TextView) view.findViewById(R.id.secondPhotoProgressText);

                viewHolder.comments = (LinearLayout) view.findViewById(R.id.commentsListView);      

                viewHolder.profilePic = (ImageButton) view.findViewById(R.id.profile);
                viewHolder.leftPic = (ImageButton) view.findViewById(R.id.photo1);
                viewHolder.rightPic = (ImageButton) view.findViewById(R.id.photo2);

                viewHolder.firstPhotoBg = (RelativeLayout) view.findViewById(R.id.firstPhotoProgress);
                viewHolder.secondPhotoBg = (RelativeLayout) view.findViewById(R.id.secondPhotoProgress);

                view.setTag(viewHolder);
            }
            else
                viewHolder = (ViewHolder) view.getTag();

    //      //imageLoader.displayImage(myUser.getProfilePicture(), viewHolder.profilePic, options);
    //      
            viewHolder.username.setText(myUser.getUserName());
            viewHolder.question.setText(question.getQuestion());

            imageLoader.displayImage(question.getRightThumbnailLink(), viewHolder.rightPic, options);
            imageLoader.displayImage(question.getLeftThumbnailLink(), viewHolder.leftPic, options);

            String url = String.format(Constants.GET_QUESTION_COMMENTS, 
                        question.getId(),
                        0,
                        2);

            ResponseCallback callback = new ResponseCallback() 
            {
                @Override
                public void onSuccess(HttpResponse response) 
                {
                    try {
                            JSONObject obj = new JSONObject(Utilities.convertStreamToString(response.getEntity().getContent()));
                            JSONArray array = obj.getJSONArray("comments");
                            ArrayList<Comment> comments = new ArrayList<Comment>();
                            for (int i = 0; i < array.length(); i ++)
                            {
                                Comment comment = Utilities.getCommentFromJSON(array.getJSONObject(i));
                                comments.add(comment);                          
                            }
                            addFeaturedViews(comments, viewHolder.comments);

                    } catch (IllegalStateException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }




                }


                @Override
                public void onFailure(HttpResponse exception) 
                {

                }
            };

            new MyAsyncTask(url, callback);
Muhammad Umar
  • 11,391
  • 21
  • 91
  • 193
  • I had a similar app, and know exactly the problem you are facing. – Phil Jun 11 '13 at 13:18
  • 4
    from a pure app architecture perspective, you should NOT ask your view to manage the download of the comments. It is the responsability of another part of your application. The "getView" job is to take information from your adapter container at position x and render it. – Gomoku7 Jun 11 '13 at 13:23
  • @user1102206 I want to get a list of Questions from server and a lot of comments for each question aND Show them just like Facebook feed. What do you recommend? – Muhammad Umar Jun 11 '13 at 13:26
  • 1
    In your activity, in the "onCreate" function, start the asynctask that download all questions and comments. On success, put them in an arraylist (the one linked to your adapter). Then use notifydatasetchanged on the adapter to refresh the list view. – Gomoku7 Jun 11 '13 at 13:32

4 Answers4

1

"there is absolutely no guarantee on the order in which getView() will be called nor how many times" (Romain Guy @ here). This method is called for example, when an element goes off-screen and then appears again after scrolling the ListView. So you should never make a call to your server from getView: instead, you should execute your asynctask outside the adapter (in a fragment or activity, for example, before instantiating the adapter), and then call notifyDataSetChanged on your list.

Community
  • 1
  • 1
Dhanesh Budhrani
  • 190
  • 3
  • 15
0

you could try this:

if(position==0)
{
    new MyAsyncTask(url, callback);
}

*Modifying the answer after seeing the information given by Dhanesh Budhrani in the comment below *

If you want to run new MyAsyncTask(url, callback); only once, you could try this:

 if(firsttime)
 {
     firsttime = false;
     new MyAsyncTask(url, callback);
 }

here firsttime is a boolean variable initialized to true in the adapter's constructor.

SKK
  • 5,261
  • 3
  • 27
  • 39
0

As already mentioned in the comments, the adapter's task is to provide views for the ListView to render. You should handle the data requests in a different class, provide the data to the Adapter and then call notifyDataSetChanged on the ArrayAdapter.

user1841833
  • 141
  • 1
  • 1
  • 3
0

Since the adapter class is directly interacting with ListView, the correct way is not to call any threads directly on it. As you will scroll your ListView/View, the getView() method will be called up again and again and AsyncTask will be called up hindering the smooth flow of ListView.

In order to deal with the situation, call the AsyncTask in your Activity class and as soon as the result is fetched in onSuccess(), define the CustomAdapterClass and call the listView.setAdapter(customAdapter) in it and pass the data in ArrayList as a Constructor of CustomArrayAdapter(ArrayList arrayListJsonResponse) and inflate the data.

Hope it helps. Thanks.

abhy
  • 933
  • 9
  • 13