PowerMan2015
PowerMan2015

Reputation: 1418

Android GridView Redraw issues

I have created an app which allows the user to take a picture, upload to a web server. This image then becomes visible on a gridview within an activity

I though everything was working ok, however the more picture i took the more problems i noticed

The images within the gridview appear to be redrawing themselves as the user begins to scroll, effectively showing the user the same images again (not always in the same order)

I have read other posts where people have struggled with something similar, however the fixes dont seem to work for me

GridView Redraw Problems

Thanks in advance for all that help

here is my gridview activity

package com.example.alex.jsonparsegridview;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

public class MainActivity extends Activity {

    GridView gridView;

    static final String[] MOBILE_OS = new String[]{
            "Android", "iOS", "Windows", "Blackberry"};

    @Override
    public void onCreate(Bundle savedInstanceState) {

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

        new JSONParse().execute();

        TextView tv = (TextView)findViewById(R.id.footerText);


        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                Intent myIntent = new Intent(MainActivity.this, CameraActivity.class);
                myIntent.putExtra("dir", "BS"); //Optional parameters
                MainActivity.this.startActivity(myIntent);
            }
        });


    }


    private class JSONParse extends AsyncTask<String, String, JSONArray> {
        private ProgressDialog pDialog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            pDialog = new ProgressDialog(MainActivity.this);
            pDialog.setMessage("Getting Data ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();

        }

        @Override
        protected JSONArray doInBackground(String... args) {

            JSONParser jParser = new JSONParser();

            // Getting JSON from URL

            String url = "http://www.500kgiveaway.co.uk/getimagesmob.php";
            JSONArray json = jParser.getJSONFromUrl(url);
            return json;
        }

        @Override
        protected void onPostExecute(JSONArray json) {
            pDialog.dismiss();
                // Getting JSON Array from URL

                JSONArray android = json;


                //copied from onCreate
                gridView = (GridView) findViewById(R.id.gridView1);

                gridView.setAdapter(new ImageAdapter(MainActivity.this, android));

                gridView.setOnItemClickListener(new OnItemClickListener() {
                    public void onItemClick(AdapterView<?> parent, View v,
                                            int position, long id) {
                        Toast.makeText(
                                getApplicationContext(),
                                ((TextView) v.findViewById(R.id.grid_item_label))
                                        .getText(), Toast.LENGTH_SHORT).show();
                    }
                });

                //End Copy





        }
    }
}

And here is my Image adaptor (custom with picasso)

package com.example.alex.jsonparsegridview;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class ImageAdapter extends BaseAdapter {
    private Context context;
    private JSONArray android;
    private String TAG_PATH = "path";
    ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();


    public ImageAdapter(Context context,  JSONArray android) {
        this.context = context;
        this.android = android;
    }

    public View getView(int position, View convertView, ViewGroup parent) {


        View gridView = null;

             try {
                 if (convertView == null) {

                     LayoutInflater inflater = (LayoutInflater) context
                             .getSystemService(Context.LAYOUT_INFLATER_SERVICE);


                 JSONObject c = android.getJSONObject(position);

                // Storing  JSON item in a Variable
                String path = c.getString(TAG_PATH);

                // Adding value HashMap key => value

                HashMap<String, String> map = new HashMap<String, String>();

                map.put(TAG_PATH, path);

                oslist.add(map);

                gridView = new View(context);

                // get layout from mobile.xml
                gridView = inflater.inflate(R.layout.mobile, null);

                // set value into textview
                TextView textView = (TextView) gridView
                        .findViewById(R.id.grid_item_label);
                textView.setText(path.toString());

                // set image based on selected text
                ImageView imageView = (ImageView) gridView
                        .findViewById(R.id.grid_item_image);


                Picasso.with(context).load("http://www.500kgiveaway.co.uk/" + path).resize(400,400).into(imageView);

                 } else {
                     gridView = (View) convertView;
                 }

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

        return gridView;
    }

    @Override
    public int getCount() {
       return android.length();
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

}

Upvotes: 1

Views: 450

Answers (1)

samgak
samgak

Reputation: 24427

The issue is in your getView() function. GridView reuses views by passing them to getView() in convertView. However, these views won't necessarily already have the correct images loaded into them, they are views that were previously being used for displaying different cells in the grid at different positions. So if convertView is not null, it saves you from having to inflate the view, but you still have to load the image into it.

Re-arrange your code something like this:

public View getView(int position, View convertView, ViewGroup parent) {

    View gridView = null;

    try {
        if (convertView == null) {
             LayoutInflater inflater = (LayoutInflater) context
                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

             gridView = new View(context);

             // get layout from mobile.xml
             gridView = inflater.inflate(R.layout.mobile, null);              
        }
        else
        {
             gridView = convertView;
        }

        JSONObject c = android.getJSONObject(position);

        // Storing  JSON item in a Variable
        String path = c.getString(TAG_PATH);

        // set value into textview
        TextView textView = (TextView) gridView
                .findViewById(R.id.grid_item_label);
        textView.setText(path.toString());

        // set image based on selected text
        ImageView imageView = (ImageView) gridView
                .findViewById(R.id.grid_item_image);

        Picasso.with(context).load("http://www.500kgiveaway.co.uk/" + path).resize(400,400).into(imageView);

        // Adding value HashMap key => value
        HashMap<String, String> map = new HashMap<String, String>();
        map.put(TAG_PATH, path);
        // TODO: add some checks so you don't add it if it's already in the list? 
        oslist.add(map);

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

    return gridView;
}

I don't know what your program logic is regarding your HashMap, but you probably only want to add it to oslist the first time the image is loaded. Note that you can't use the (convertView == null) test for this because the convertView could have been used for a completely different image.

Upvotes: 1

Related Questions