5

I apologize upfront if the question is too long. Here we go:

There are two activities: Main and Detail Activity.

Main Activity is basically a GridView. Detail Activity is basically shows the clicked item's detail information. I am passing selected item's id (pid) from the Main to the Detail Activity.

I am facing an issue as follows. Initially, I have 3G connection (cellular connection) and clicked on the first item and see the corresponding item detail in the Detail Activity, it works perfectly fine, and go back to the Main Activity, then clicked on the second item, then unfortunately it still shows me the first item in the DetailActivity that I clicked initially.

I switched from 3g to wifi while app is on the active and open. No matter what I click, it still shows me the first item that I clicked initially.

But when I delete the app and reinstall it and get either wifi access only, the app works perfectly fine.

In the following implementation, Connection URL (PRODUCT_DETAIL_URL) is http, not https. I am using Volley library for the network connection.

DetailActivity.java

private void productDetailInit() {
      // it is http
        StringRequest postRequest = new StringRequest(Request.Method.POST, Config.PRODUCT_DETAIL_URL,
                new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                            try {
                                jsonObject = response;
                                loadJsonData();
                            } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        error.printStackTrace();
                    }
                }
            ) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("id", productID);
                return params;
            }
        };

        RetryPolicy policy = new DefaultRetryPolicy(1000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
        postRequest.setRetryPolicy(policy);
        CustomVolleyRequest.getInstance(this).getRequestQueue().add(postRequest);
    }

CustomVolleyRequest.java

public class CustomVolleyRequest {

private static CustomVolleyRequest customVolleyRequest;
private static Context context;
private RequestQueue requestQueue;
private ImageLoader imageLoader;

private CustomVolleyRequest(Context context) {
    this.context = context;
    this.requestQueue = getRequestQueue();

    imageLoader = new ImageLoader(requestQueue,
            new ImageLoader.ImageCache() {
                private final LruCache<String, Bitmap>
                        cache = new LruCache<String, Bitmap>(20);

                @Override
                public Bitmap getBitmap(String url) {
                    return cache.get(url);
                }

                @Override
                public void putBitmap(String url, Bitmap bitmap) {
                    cache.put(url, bitmap);
                }
            });
}

private class BitmapCache implements ImageLoader.ImageCache {

    private LruCache<String, Bitmap> mCache;

    public BitmapCache() {
        mCache = new LruCache<>(20);
    }

    @Override
    public Bitmap getBitmap(String url) {
        return mCache.get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        // scaling bitmap for avoiding too much big images
        Bitmap scaled = ImageUtil.getInstance().scaleBitmap(bitmap);
        mCache.put(url, scaled);
    }
}

public static synchronized CustomVolleyRequest getInstance(Context context) {
    if (customVolleyRequest == null) {
        customVolleyRequest = new CustomVolleyRequest(context);
    }
    return customVolleyRequest;
}

public RequestQueue getRequestQueue() {
    if (requestQueue == null) {
        Cache cache = new DiskBasedCache(context.getCacheDir(), 10 * 1024 * 1024);
        Network network = new BasicNetwork(new HurlStack());
        requestQueue = new RequestQueue(cache, network);
        requestQueue.start();
    }
    return requestQueue;
}

 public ImageLoader getImageLoader() {
    return imageLoader;
 }

}

Adapter.java

 class ProductMainAdapter extends ArrayAdapter<ImageRecord> {
    private ImageLoader mImageLoader;
    private String jsonObject;

    ProductMainAdapter(Context context) {
        super(context, R.layout.grid_item);
        mImageLoader = CustomVolleyRequest.getInstance(this.getContext()).getImageLoader();
    }

    @NonNull
    @Override
    public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
        final ViewHolder holder;
        if(convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.grid_item, parent, false);
            convertView.setBackgroundResource(R.drawable.round_gridview);
            holder.priceTagImage = (ImageView) convertView.findViewById(R.id.priceTag_IV);
            holder.textView = (TextView) convertView.findViewById(R.id.text);
            holder.imageView = (NetworkImageView) convertView.findViewById(R.id.picture);
            holder.priceTagRL = (RelativeLayout) convertView.findViewById(R.id.priceTag_RL);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }
        ImageRecord imageRecord = getItem(position);
        holder.imageView.setImageUrl(imageRecord != null ? imageRecord.getUrl() : null, mImageLoader);
        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openProductDetail(position);
            }
        });
        holder.textView.setText(imageRecord != null ? imageRecord.getTitle() : null);
        holder.priceTagRL.setRotation(0);

        return convertView;
    }

    private class ViewHolder{
        TextView textView;
        ImageView priceTagImage;
        NetworkImageView imageView;
        RelativeLayout priceTagRL;
    }

    private void openProductDetail(int position) {
        try {
            ImageRecord imr = getItem(position);
            String productID = imr != null ? imr.getId() : "0";
            Intent intent = new Intent(getContext(), ProductDetailActivity.class);
             intent.putExtra("pid", productID);
             getContext().startActivity(intent);    
        } catch (Exception e) {
            Log.e("openProductDetail", "exception", e);
        }
    }

I wonder what I am missing/ doing wrong in the provided implementation. It has been taking almost 2-3 months, I could not able to handle that issue. Has anyone ever faced a similar situation? Any suggestion or comment is highly appreciated.

casillas
  • 16,351
  • 19
  • 115
  • 215
  • Duplicate of http://stackoverflow.com/questions/41195367/android-gridview-opens-the-same-entry-the-first-clicked-one-in-subsequent-cli – Selvin Dec 17 '16 at 22:21
  • Question is why don't you obtain data in ProductDetailActivity itself ... and from gridview start the new activity only – Selvin Dec 17 '16 at 22:32
  • @Selvin, I need to pass the clicked item `id` to the `ProductDetailActivity`, where I am using this `id` for URL call to get all information such as `product price, product images, product location, seller name and seller city`... In other words, I am also doing network operation in the `ProductDetailActivity` as well. – casillas Dec 17 '16 at 22:35
  • @Selvin, I have added the missing code, and refined the adapter class. I would be glad if you have a chance to look at it. – casillas Dec 17 '16 at 22:43
  • Is it possible in `openProductDetail` you're getting a null ImageRecord and keep passing through "0" as the id? Is "0" mapped to a product and is it the one your user kept seeing? – Dom Dec 18 '16 at 00:33
  • @Dom, no there is no item id equals to 0. – casillas Dec 18 '16 at 01:13
  • Could you post the adapter code? – Austin Hanson Dec 20 '16 at 21:28
  • @AustinHanson, I have added the adapter as well. Please let me know if you need anything else. Thank you so much in advance. I have also added screenshots. – casillas Dec 20 '16 at 21:51
  • @Selvin, I have added more detail information and also put bounty (+50) – casillas Dec 20 '16 at 21:59
  • Inside `onItemClick` pls try using `Toast` right before `openProductDetail(position);` to display the position value. Or try using `Intent.FLAG_ACTIVITY_CLEAR_TASK` or `Intent.FLAG_ACTIVITY_CLEAR_TOP`...before `startActivity(intent);` – BNK Dec 21 '16 at 03:11
  • @BNK, `onItemClick` returns the right position. `Intent.FLAG_ACTIVITY_CLEAR_TASK` or `Intent.FLAG_ACTIVITY_CLEAR_TOP` are also tested but no luck. – casillas Dec 21 '16 at 16:59
  • @BNK, I have tested application with two different Internet providers : `3G` and `WIFI`. Application works perfectly fine with `WIFI` but when I switched to `3G` then it starts giving the same issue. – casillas Dec 21 '16 at 18:32
  • Does Volley do any sort of caching where if there is no internet connection it returns the last result? – Austin Hanson Dec 21 '16 at 18:48
  • @AustinHanson, here is the scenario that I have tested. I started with `3g` and clicked on the first item and see the item detail, it is perfectly fine. and go back to main. then click on the second item, then it still shows me the first item in the `DetailActivity` that I clicked initially. Then I switched to `wifi` when app is open, no matter what I click it shows me the first item that I clicked initially. But when I delete the app and reinstall it and get wifi access only, app works perfectly fine. – casillas Dec 21 '16 at 19:23
  • @AustinHanson, I have added `Volley` class into the question. – casillas Dec 21 '16 at 19:34
  • http://stackoverflow.com/questions/41270574/app-works-on-wifi-but-not-on-3g – casillas Dec 21 '16 at 20:56
  • The code you posted in that question is different - you don't use gridView.setOnItemClickListener() and instead set one on the viewHolder. Are you actually doing both? You check for a network connection in the viewHolder openProductDetail but not in the gridView - this maybe the reason why? – Austin Hanson Dec 21 '16 at 22:15
  • @AustinHanson, does it really matter to get clicked item position in the `adapter` vs `gridview` ? just in case, I have implemented in that way as well, but I get the same position. I have tested both version with `3G`, both did not work... However both works with `Wifi` connection. – casillas Dec 21 '16 at 22:20
  • But you weren't using *both* at the same time, right? That was my concern, if you were using both... The position should be reported correctly. If you can reproduce consistently, set a breakpoint at the code that creates the intent and in onCreate of the detail activity and check the values of the extra. – Austin Hanson Dec 21 '16 at 23:45
  • @AustinHanson, no I am not using both at the same time. By the way, I have tested application on 4G in adddition to WIFI, it works.. but 3G does not. – casillas Dec 22 '16 at 04:57
  • have you tried to debug this? what is a point of wrong direction ? does it pass correct id to DetailActivity ? does it call the correct url ? does it receive correct data ? does data be parsed correct ? – Orest Savchak Dec 27 '16 at 14:35
  • Are you sure your 3G ISP is returning the HTTP you expect, not a cached or modified version of what you expected from the server? Have you tried other devices on other 3G networks? Or does the HTTP response have headers that tell the client to cache the request and it is incorrect so it is caching different requests under the same key? – Jon Adams Dec 27 '16 at 14:57

3 Answers3

2

You could just kill the activities with finish(); when the other one loads.

EpicCodez
  • 85
  • 4
0

I was also having the same problem. In my case in onClick method the position was not correct. Then I used to set the position as a tag to the specific view which has OnClickListener set and my problem solved. It may be due to the position is declared as final. So remove the final keyword and try like this.

holder.imageView.setImageUrl(imageRecord != null ? imageRecord.getUrl() : null, mImageLoader);
holder.imageView.setTag(position);
holder.priceTagRL.setRotation(0);

And in onClick method

openProductDetail((int)view.getTag());
Gopal Singh Sirvi
  • 4,539
  • 5
  • 33
  • 55
0

Check if the below link can be helpful:

https://stackoverflow.com/a/33682366/2798289 (3G connection might actually be slow that you to have increase the threshold of timeout)

Also, there is a chance the position reference in the adapter can come wrong in some edge case (irrespective of your actual issue). You can try the below alternative method..

Use gridView.setOnItemClickListener

gridview.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v,
                int position, long id) {
            //do your logic based on the position
        }
    });

Note: In case if GridView is not able to observe the item click event, you have to set android:descendantFocusability="blocksDescendants" to the child root view under gridview. This might happen basically because the GridView items should not be clickable by itself as it will observe the click event.

Reference: https://developer.android.com/guide/topics/ui/layout/gridview.html

Community
  • 1
  • 1
Govind
  • 2,482
  • 1
  • 28
  • 40