0

I have made a gridview in which i have tried to add next feature in that grid. When someone clicks on "next", the grid is loaded with new bunch of images.

I have made a logic and somehow it is working but it is not stable. App gets stopped sometimes and sometime on clicking "next" the next page get skipped (Suppose currently i am on page 0 and when i click on "next" grid gets refreshed and page 2 is shown instead of page 1)

What i am doing is I have made a asynctask which send http request to the php server for new urls of images. then i refresh the gridview and display the new images from new image urls.

Code

public class UserPage extends Activity {


ImageAdapter ia = new ImageAdapter(this);
GetResponse task = new GetResponse(0);
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.userpage);

    final GridView gridview = (GridView) findViewById(R.id.gridview);

    gridview.setAdapter(ia);
    gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);

    Button nxt = (Button) findViewById(R.id.nextbuttongrid);
    nxt.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            // next page
            int i = Integer.parseInt(GetResponse.counter);
            i=i+1;
            GetResponse.counter = Integer.toString(i);
            String x = GetResponse.response;
            task.execute();
        //this is done so that the thread sleeps until the response variable value is updated  
            while(x.equals(GetResponse.response)==true){
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    System.out.println("Here in sleep..incre");
                } }
            change(gridview);
        }
    });

    Button pre = (Button) findViewById(R.id.previousbuttongrid);
    pre.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            // previous page
            int i = Integer.parseInt(GetResponse.counter);
            i=i-1;
            GetResponse.counter = Integer.toString(i);
            String x = GetResponse.response;
            task.execute();
           //this is done so that the thread sleeps until the response variable value is updated  
            while(x.equals(GetResponse.response)==true){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("Here in sleep.. decre");
            } }
            change(gridview);

        }
    });

    /**
     * On Click event for Single Gridview Item
     * */
     gridview.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View v,
                int position, long id) {

            // Sending image id to FullImage.java
            Intent i = new Intent(getApplicationContext(), FullImage.class);
            i.putExtra("id", position);
            startActivity(i);
        }
    });
}

void change(GridView gridview) {
    ia = new ImageAdapter(this);
    gridview.invalidateViews();
    gridview.setAdapter(ia);
}
}
public class GetResponse extends AsyncTask<Void, Void, Void> {

  public static String counter = "0";

  HttpPost httppost;
  StringBuffer buffer;
  HttpResponse response1;
  HttpClient httpclient;
  List<NameValuePair> nameValuePairs;

  public static String response;


    @Override
    protected Void doInBackground(Void... params) {

try {
    Log.d("response's Value == >", "Response previous " + response);
    httpclient=new DefaultHttpClient();
    httppost= new HttpPost(ServerAdressHere); 
    //add your data
    nameValuePairs = new ArrayList<NameValuePair>(3);

    nameValuePairs.add(new BasicNameValuePair("username",AndroidPHPConnectionDemo.userName)); 
    nameValuePairs.add(new BasicNameValuePair("password",AndroidPHPConnectionDemo.passWord));
    nameValuePairs.add(new BasicNameValuePair("count",counter));
    Log.d("Counter's Value == >", "Counter " + counter);
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    //Execute HTTP Post Request
    response1=httpclient.execute(httppost);
    ResponseHandler<String> responseHandler = new BasicResponseHandler();
    response = httpclient.execute(httppost, responseHandler);
    Log.d("response's Value == >", "Response after " + response);
}
    catch(Exception e){
        System.out.println("Exception Here"+e);
    }
  return null;

    }
   }
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private TextView txtUrl;
private String response;
public ImageView imageView;
public static String[] mThumbIds;

  public ImageAdapter(Context c) {
    mContext = c;
    this.response = GetResponse.response.trim();
    mThumbIds = response.split(",");
    }

private final Downloader imageDownloader = new Downloader(mContext);


public int getCount() {
    return mThumbIds.length;
}

public Object getItem(int position) {
    return mThumbIds[position];
}

public long getItemId(int position) {
    return mThumbIds[position].hashCode();
}

// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {

    if(convertView==null) {
        imageView = new ImageView(mContext);
        imageView.setLayoutParams(new GridView.LayoutParams(LayoutParams.MATCH_PARENT, 195));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(10, 10, 10, 10);
    }

    else {
         imageView = (ImageView) convertView;
         }

    imageDownloader.DisplayImage(mThumbIds[position], (ImageView) imageView);

    return imageView;
}

public Downloader getImageDownloader() {
    return imageDownloader;
}
}

"counter" variable(static and String type) is sent in the request which tells the page number of the next gridview to php server. So the server will send the image urls tied to that page number.

The problem i am faciing is that the grid gets refreshed before "response" variable is updated by the asynctask class. So thats why i have used System.sleep() so as to get time gap b/w execution of two lines of code.

"response" variable(Static and integer type) contains the image urls.

Please help ! and if some more details are required please ask.

Shubham Arora
  • 167
  • 13
  • 2
    change() should be called in onPostResult – njzk2 Apr 02 '13 at 13:30
  • i think its onPostExecute not onPostResult and i have moved the code of change() into onPostExecute method of my asynctask class but its not working.. the grid is not getting refreshed. :/ – Shubham Arora Apr 02 '13 at 15:52
  • you'll have to post code from your adapter and from your asynctask – njzk2 Apr 02 '13 at 16:38
  • Can you please tell me that how can i run UI thread inside onPostExecute ? – Shubham Arora Apr 02 '13 at 18:22
  • onPostExecute is on the ui thread. read the doc. – njzk2 Apr 03 '13 at 07:51
  • okay! thanks for the information. But as u said i have shifted the code inside change() method inside onPostExecute method but its not working :/ – Shubham Arora Apr 05 '13 at 14:49
  • define "not working". it can mean all manner of things, from not compiling to crashing at some point to not having the expected behaviour. One cannot guess what you mean by that unless you are more specific. – njzk2 Apr 05 '13 at 15:34
  • not working means that when i click on next.. i am getting new urls of images but the grid is not getting refreshed. In my asynctask class i have declared a static variable which of string type. url of images are saved in that string variable.. and i am using this variable in my Adapter class to display images in grid.. when i click on next the string variable is getting updated and new urls get stored in it but grid is getting reloading with new images. – Shubham Arora Apr 05 '13 at 19:56
  • postmore code. the async task, for one, and probably the adapter will be useful as well. – njzk2 Apr 07 '13 at 15:18
  • I have posted more code as you said. Please check it. I have also tried using ia.notifyDataSetChanged() in onPostExecute() method instead of using change() method. But that also haven't worked for me. And the above code is able to load only one next page. And after it when again next/previous is clicked the app gets stopped. – Shubham Arora Apr 08 '13 at 14:36

1 Answers1

0

First of all, Thread.sleep in a loop in the onClick method is not a proper way of doing this. the whole point of the asynctask is to avoid locking the main thread, and Thread.sleep is doing just that.

Use your asynctask's onPostExecute instead.

However, this apparently works so far (your server and connection are quick enought otherwise you'd have an ANR) even though your ui probably freezes for a few seconds.

After that, there is the matter of the images download. Calling setAdapter(new Adapter...) seems like a good enough way.

How far have you gone with step by step debugging ?

  • do you receive the image id list in line Log.d("response's Value == >", "Response after " + response); ?
  • do you reach getView, and if so do you get there with the right url/id/string, whatever is supposed to be in mThumbIds[position] ?
  • If so, what is a Downloader and how does it work ?

out of curiosity, why do you execute the request twice ? (response1=httpclient.execute(httppost);)

edit

I can't really believe you didn't though it was interesting to mention your app was actually crashing, which is quite different from 'the grid is not getting refreshed'.

You have to

A/ read you stack trace.

B/ if it's not clear, google it.

C/ I don't know what else can be added to (a task can be executed only once)

njzk2
  • 38,969
  • 7
  • 69
  • 107
  • As per the debugging.. I reach Log.d("response's Value == >", "Response after " + response); only two times only and with correct values. Firstly, when the first page is loaded. Secondly when i click on next button and second page is loaded. I am getting the correct views both the time. The app gets stopped when next button is clicked for the second time and at that time i am not receiving image id list in line Log.d("response's Value == >", "Response after" + response); "Downloader" is a class which manage caching with other classes. – Shubham Arora Apr 08 '13 at 17:44
  • I'm using thread.sleep because change() gets executed before the work of asynctask class is completed. And grid get refreshed with the old urls or can say with old values in mThumbIds[]. – Shubham Arora Apr 08 '13 at 17:46
  • i understand why you use sleep. but it is not how it is done. call `change()` from within the onPostExecute of your asynctask. you are freezing the main thread, which results in bad user experience. – njzk2 Apr 09 '13 at 07:37
  • can you post your log from when you click the next button the second time ? – njzk2 Apr 09 '13 at 07:43
  • I have updated my question with the logs as you asked. Actually when for very first time grid is loaded.. the request for image is made through same GetResponse asynctask class. So i cannot wirte code to refresh grid in onPostExecute, as there is no need to refresh the grid first time. Do you have any idea abt it ? – Shubham Arora Apr 09 '13 at 13:38
  • no i haven't it yet.. actually i'm new to android development so know less about it. Now i will read the stacktrace and will tell you. Between do you have any idea why and where the problem is occurred due to which app is getting crashed when i click next button second time ? – Shubham Arora Apr 09 '13 at 19:19
  • Sir thanks you so much for the help. The problem has been solved. Actually every time i have to create object of Asynctask class but i have created the object once and calling task.execute more than once but it can be executed once. :) Do you know what is logic behind this ? – Shubham Arora Apr 09 '13 at 19:42
  • And do you know what should i do instead of using Thread.sleep . And my reason for using it can be achieved ? – Shubham Arora Apr 09 '13 at 19:47
  • you have to implement onPostExecute in your async task and call `change()` from there. There are tons of tutorials regarding asynctasks, i recommend you read a few to get a better notion of how it is supposed to be used. – njzk2 Apr 10 '13 at 08:25
  • to call change i have to make object of my UserPage class inside onPostExecute and then i can call change using object ref variable. Right ? – Shubham Arora Apr 10 '13 at 13:42
  • you have to either pass your UserPage to your asynctask, or make your asynctask an inner class of UserPage. – njzk2 Apr 10 '13 at 13:55
  • okay! thank u so much for your help.:) Sorry i cannot vote up your answer at present i don't have sufficient reputation to do that. :/ – Shubham Arora Apr 11 '13 at 19:09