Custom Listview scroll hiding progressbar process and ImageView
Asked Answered
H

5

5

I have a custom Listview, where each item contains a progressbar. But when the list contains many items, and I use the scrollbar to navigate through listview, some ProgressBars disappear and facing same issue with imageview using to show status of uploaded image(s), what could be the reason and how can i resolve this ? see my code below

    static class ViewHolder {
        public ViewHolder(View convertView) {
            // TODO Auto-generated constructor stub
        }
        TextView imageNameTextView;
        ImageView sdCardImageView, statusImageView;
        ProgressBar uploadProgressBar;
        ImageButton uploadImageButton, dataImageButton, printImageButton, viewImageButton, deleteImageButton ;
    }  
     public class ImageAdapter extends BaseAdapter
        {
            public ImageAdapter(Context c)
            {
            }

            public int getCount() {
                // TODO Auto-generated method stub
                return ImageList.size();
            }

            public Object getItem(int position) {
                // TODO Auto-generated method stub
                return position;
            }

            public long getItemId(int position) {
                // TODO Auto-generated method stub
                return position;
            }

    public View getView(final int position, View convertView, ViewGroup parent) {
        // Avoid unneccessary calls to findViewById() on each row, which is expensive!
        holder = null;

            // If this item is to be synced
            if(flags.get(position)) {
                startUpload(position);

            // Mark as synced
            flags.put(position, false);
            }

            /*
             * If convertView is not null, we can reuse it directly, no inflation required!
             * We only inflate a new View when the convertView is null.
             */
            if (convertView == null) {
            convertView = getLayoutInflater().inflate(R.layout.list_upload, null);
            holder = new ViewHolder(convertView);

            // Create a ViewHolder and store references to the children views
            holder.imageNameTextView = (TextView) convertView.findViewById(R.id.ColImgName);
            holder.sdCardImageView = (ImageView) convertView.findViewById(R.id.ColImgPath);
            holder.statusImageView = (ImageView) convertView.findViewById(R.id.ColStatus);
            holder.uploadProgressBar = (ProgressBar) convertView.findViewById(R.id.progressBar);
            holder.uploadImageButton = (ImageButton) convertView.findViewById(R.id.btnUpload);
            holder.dataImageButton = (ImageButton) convertView.findViewById(R.id.btnData);
            holder.printImageButton = (ImageButton) convertView.findViewById(R.id.btnPrint);
            holder.viewImageButton = (ImageButton) convertView.findViewById(R.id.btnView);
            holder.deleteImageButton = (ImageButton) convertView.findViewById(R.id.btnDelete);

                // The tag can be any Object, this just happens to be the ViewHolder
                convertView.setTag(holder);
            } else {

                holder = (ViewHolder) convertView.getTag();
            }

            strPath = ImageList.get(position).toString();

            // Get File Name
            fileName = strPath.substring( strPath.lastIndexOf('_')+1, strPath.length() );
            file = new File(strPath);
            @SuppressWarnings("unused")
            long length = file.length();
            holder.imageNameTextView.setText(fileName);

            final BitmapFactory.Options options = new BitmapFactory.Options();

            options.inSampleSize = 8;

            Bitmap bm = BitmapFactory.decodeFile(strPath,options);
            holder.sdCardImageView.setImageBitmap(bm);       

            holder.statusImageView.setImageResource(R.drawable.bullet_button);

            holder.uploadProgressBar.setVisibility(View.GONE);

            //btnUpload
            holder.uploadImageButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            // Upload
                 cd = new ConnectionDetector(getApplicationContext());

                    // Check for internet connection
                    if (!cd.isConnectingToInternet()) {
                        // Internet Connection is not present
                        alert.showAlertDialog(UploadActivity.this, "Internet not available",
                                "Please connect to working Internet connection", false);
                        // stop executing code by return
                        return;
                    }

                    startUpload(position);
                }
            });

         //Upload
    public void startUpload(final int position) {      

        Runnable runnable = new Runnable() {

        public void run() {

            handler.post(new Runnable() {

        public void run() {

            v = lstView.getChildAt(position - lstView.getFirstVisiblePosition());

            holder.uploadProgressBar.setVisibility(View.VISIBLE);

            holder.statusImageView.setImageResource(R.drawable.bullet_button);

                new UploadFileAsync().execute(String.valueOf(position));   
                        }
                    });
                }
            };
            new Thread(runnable).start();
            }

            // Async Upload
            public class UploadFileAsync extends AsyncTask<String, Void, Void> {

                String resServer;

            protected void onPreExecute() {
                super.onPreExecute();
            }

            @Override
            protected Void doInBackground(String... params) {
            // TODO Auto-generated method stub
                position = Integer.parseInt(params[0]);

                int bytesRead, bytesAvailable, bufferSize;
                byte[] buffer;
                int maxBufferSize = 1 * 1024 * 1024;
                int resCode = 0;
                String resMessage = "";

                String lineEnd = "\r\n";
                String twoHyphens = "--";
                String boundary =  "*****";

                // File Path
                String strSDPath = ImageList.get(position).toString();

                // Upload to PHP Script
                String strUrlServer = "http://domein/fiile.php";

                try {
                    /** Check file on SD Card ***/
                    File file = new File(strSDPath);
                    if(!file.exists())
                    {   
                        resServer = "{\"StatusID\":\"0\",\"Error\":\"Please check path on SD Card\"}";
                        return null;
                    }

                FileInputStream fileInputStream = new FileInputStream(new File(strSDPath));

                URL url = new URL(strUrlServer);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setDoInput(true);
                    conn.setDoOutput(true);
                    conn.setUseCaches(false);
                    conn.setRequestMethod("POST");

                    conn.setRequestProperty("Connection", "Keep-Alive");
                    conn.setRequestProperty("Content-Type",
                            "multipart/form-data;boundary=" + boundary);

                DataOutputStream outputStream = new DataOutputStream(conn
                        .getOutputStream());
                    outputStream.writeBytes(twoHyphens + boundary + lineEnd);
                    outputStream
                    .writeBytes("Content-Disposition: form-data; name=\"filUpload\";filename=\""
                            + strSDPath + "\"" + lineEnd);
                    outputStream.writeBytes(lineEnd);

                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                buffer = new byte[bufferSize];

                // Read file
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                while (bytesRead > 0) {
                    outputStream.write(buffer, 0, bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                }

                outputStream.writeBytes(lineEnd);
                outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

                // Response Code and  Message
                resCode = conn.getResponseCode();
                    if(resCode == HttpURLConnection.HTTP_OK)
                    {
                        InputStream is = conn.getInputStream();
                        ByteArrayOutputStream bos = new ByteArrayOutputStream();

                int read = 0;
                while ((read = is.read()) != -1) {
                    bos.write(read);
                }

                byte[] result = bos.toByteArray();
                    bos.close();

                resMessage = new String(result);

                }

                Log.d("resCode=",Integer.toString(resCode));
                Log.d("resMessage=",resMessage.toString());

                fileInputStream.close();
                outputStream.flush();
                outputStream.close();

                resServer = resMessage.toString();


                } catch (Exception ex) {
                    ex.printStackTrace();
                }

                return null;
                }

                protected void onPostExecute(Void unused) {
                    statusWhenFinish(position,resServer);
                    }

                }


            // When UPload Finish
            @SuppressWarnings("unused")
            protected void statusWhenFinish(int position, String resServer) {

            View v = lstView.getChildAt(position - lstView.getFirstVisiblePosition());

            // hide ProgressBar
            holder.uploadProgressBar.setVisibility(View.GONE);


            /*** Default Value ***/
            String strStatusID = "0" ;
            String strError = "" ;

            try {      

            JSONObject c = new JSONObject(resServer);
            strStatusID = c.getString("StatusID");
            strError = c.getString("Message");
            } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }

            // using if - else if
            if(strStatusID.equals("0"))
            {   
                // already exist
              holder.statusImageView.setImageResource(R.drawable.already_exist);
            }
            else if(strStatusID.equals("1"))                {
                // upload done
                holder.statusImageView.setImageResource(R.drawable.upload_done);
            }
            else // if upload failed
            {
                 // upload failed
                holder.statusImageView.setImageResource(R.drawable.upload_failed);
            }

            }

         }
Harrisharrisburg answered 21/3, 2014 at 8:35 Comment(2)
what you want to do you want to display image with progress bar ?Rainie
First of all your usage of "ViewHolder" pattern is invalid. You should not store a reference to any ViewHolder in your Adapter/Activity/anywhere. Basically, ViewHolder is created,attached,referenced to in getView(..) method, and nowhere else. Your problems are caused by illegal usage of the ViewHolder and one of the most terrific Thread/Runnable usage I've ever seen. Rework your code, I'm pretty sure you have no need for those "matrioshka" threads at all.Exceed
C
2

In your ViewHolder class :

static class ViewHolder {
     //...
     boolean isUploading = false;
     //...
}

In your getView():

public View getView(final int position, View convertView, ViewGroup parent) {
     //...
     if(holder.isUploading) {
           holder.uploadProgressBar.setVisibility(View.VISIBLE);
     } else {
           holder.uploadProgressBar.setVisibility(View.GONE);
     }
     //...
}

In your startUpload():

public void startUpload(final int position) { 
     //...
     holder.uploadProgressBar.setVisibility(View.VISIBLE);
     holder.isUploading = true;
     //...
}

Hope it will work.

Chamade answered 4/4, 2014 at 6:23 Comment(0)
U
2

So for your ProgressBar.

Whenever getView() is called, you set its visibility to GONE.

holder.uploadProgressBar.setVisibility(View.GONE);

So when starts to upload something (and sets uploadProgressBar to VISIBLE), and you scroll down (makes the list item invisible), then scroll up, getView() will be called again, and it will make your ProgressBar invisible.

So you need wrap the state in an object, or use a list to record each item state. For example, in your ImageAdapter

boolean[] uploadings = new boolean[getCount()];
Arrays.fill(uploadings, false);

in your getView()

if (uploadings[position]) {
    // You need this, since you are not sure whether you are
    // using newly inflated view or ConvertView
    holder.uploadProgressBar.setVisibility(View.VISIBLE);
} else {
    holder.uploadProgressBar.setVisibility(View.GONE);
}

And in your startUpload() method, whenever you set your prograss bar to GONE or VISIBILE, set uploadings[position] to false or true correspondingly.

And I think your ImageView probably has the same problem.

Uncounted answered 3/4, 2014 at 2:7 Comment(1)
i tried but not getting exactly, can you show me the way by making changes in my existing code ???Harrisharrisburg
C
2

In your ViewHolder class :

static class ViewHolder {
     //...
     boolean isUploading = false;
     //...
}

In your getView():

public View getView(final int position, View convertView, ViewGroup parent) {
     //...
     if(holder.isUploading) {
           holder.uploadProgressBar.setVisibility(View.VISIBLE);
     } else {
           holder.uploadProgressBar.setVisibility(View.GONE);
     }
     //...
}

In your startUpload():

public void startUpload(final int position) { 
     //...
     holder.uploadProgressBar.setVisibility(View.VISIBLE);
     holder.isUploading = true;
     //...
}

Hope it will work.

Chamade answered 4/4, 2014 at 6:23 Comment(0)
B
1

try to use a holder for your cell view

put this class at the end of your adapter

class ViewHolder {
        TextView txtName,txtStatus;

        ImageView imageView;

        public ViewHolder(View convertview) {
            txtName = (TextView) convertview.findViewById(R.id.txtName );
            imageView = (ImageView) convertview.findViewById(R.id.ColImgPath);
          //and so on...


        }
    }

replace:

 if (convertView == null) {
        convertView = inflater.inflate(R.layout.list_upload, null);
    }

with:

 if (convertview == null) {
            convertview = activity.getLayoutInflater().inflate(R.layout.list_upload, null);
            holder = new ViewHolder(convertview);
            convertview.setTag(holder);
        } else {
            holder = (ViewHolder) convertview.getTag();
        }

after that do your job with holder...

holder.imageView instead of imageView and so on for all views

Bontebok answered 28/3, 2014 at 10:13 Comment(0)
A
1

You must set progress state in getView() method because android reuse ListView items. to get you a clue how to resolve this:

`

 public View getView(final int position, View convertView, ViewGroup parent) {
    .
    .
    .
Int rowId = holder.id;
UploadTask task = Uploader.getTaskById(rowId);
if (task == null) {
holder.progressBar.setVisibility(View.Gone);
} else {
int progress = task.getUploadProgress();
holder.progressBar.setVisibility(View.Visible);
holder.progressBar.setProgress(progress);
}
    }

p.s. You should watch this Google IO video about listviewListView

Absolution answered 1/4, 2014 at 17:31 Comment(0)
M
1

Check out the Listview with ProgressBar it might help you

Maddalena answered 3/4, 2014 at 13:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.