Why does not work notifyItemChanged

6.2k views Asked by At

I understand that it is possible a silly question but I can not find the answer to it. I ask your help.

I have a RecyclerView using a LinearLayoutManager, and a custom RecyclerView.Adapter.

My data class:

public class Img extends ArrayList<Img> {
    int id = 0;
    String filepath = "";
    boolean checked = false;
    int progress = 0;

    ... getters and setters...
}

Code in activity:

    File folder = new File("My path");
    File[] files = folder.listFiles();
    int id = 0;
    for (File file : files) {
        if (!file.isDirectory()) {
            Img img = new Img();
            img.setId(id);
            img.setFilepath(file.toString());
            imgs.add(img);
            ++id;
        }
    }

    mAdapter = new GalleryAdapter(getApplicationContext(), imgs);
    RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(), 2);
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(mAdapter);

and adapter:

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        Img item = imgs.get(position);
        holder.txt.setText(String.valueOf(item.getProgress()));
        holder.thumbnail.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               File source = new File(imgs.get(position).getFilepath());
               String strFileName = source.getName();
               File destination = new File("My path" + "/" + strFileName);

               try {
                   InputStream input = null;
                   OutputStream output = null;
                   long lenghtOfFile = source.length();
                   int count;
                   try {
                       input = new FileInputStream(source);
                       output = new FileOutputStream(destination);
                       byte[] data = new byte[1024];
                       long total  = 0;
                       int xc2 = 0;
                       while ((count = input.read(data)) != -1) {
                          total += count;
                          int xc = (int) ((total * 100) / lenghtOfFile);

                          output.write(data, 0, count);
                          imgs.get(position).setProgress(xc);
                          notifyItemChanged(position);
                          try {
                              Thread.sleep(20);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  } finally {
                   output.flush();
                   output.close();
                   input.close();
                  }
            } catch (IOException e) {
               e.printStackTrace();
            }
        }
  });

Why notifyItemChanged (position) is triggered only after the operation is completed and submitted to the TextView (txt) only the value of 100?

UPD: This code does not work

@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
    final View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.gallery_thumbnail, parent, false);

    final MyViewHolder holder = new MyViewHolder(itemView);

    itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = holder.getAdapterPosition();
            if (position != RecyclerView.NO_POSITION) {
                File source = new File(imgs.get(position).getFilepath());
                String strFileName = source.getName();
                File destination = new File("My path" + "/" + strFileName);

                try {
                    InputStream input = null;
                    OutputStream output = null;
                    long lenghtOfFile = source.length();
                    int count;
                    try {
                        input = new FileInputStream(source);
                        output = new FileOutputStream(destination);
                        byte[] data = new byte[1024];
                        long total  = 0;
                        int xc2 = 0;
                        while ((count = input.read(data)) != -1) {
                            total += count;
                            int xc = (int) ((total * 100) / lenghtOfFile);
                            output.write(data, 0, count);
                            if (xc2!=xc){
                                //holder.progress_bar.setProgress(xc);
                                imgs.get(position).setProgress(xc);
                                notifyItemChanged(position);
                                try {
                                    Thread.sleep(40);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            xc2 = xc;
                        }
                    } finally {
                        output.flush();
                        output.close();
                        input.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    });

    return holder;
}

UPD2: This code does not work

@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.gallery_thumbnail, parent, false);

    final MyViewHolder holder = new MyViewHolder(itemView);

    itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = holder.getAdapterPosition();
            if (position != RecyclerView.NO_POSITION) {
                for (int i=1; i<=100; ++i) {
                    imgs.get(position).setProgress(i);
                    notifyItemChanged(position);
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    });

    //return new MyViewHolder(itemView);
    return holder;
}
1

There are 1 answers

0
Yakir Yehuda On BEST ANSWER

Basically your'e doing your'e file loading on the UI thread, so everytime you call to notifyItemChanged() you add a task to the Looper but the Looper gets to that task only when you finish the loading therefor you only see the 100.

I would run the load on a different thread like so:

new View.OnClickListener() {
        @Override
        public void onClick(View view) {
           File source = new File(imgs.get(position).getFilepath());
           String strFileName = source.getName();
           File destination = new File("My path" + "/" + strFileName);
           **> Thread t1 = new Thread(new Runnable(){
           public void run(){ <**
           try {
               InputStream input = null;
               OutputStream output = null;
               long lenghtOfFile = source.length();
               int count;
               try {
                   input = new FileInputStream(source);
                   output = new FileOutputStream(destination);
                   byte[] data = new byte[1024];
                   long total  = 0;
                   int xc2 = 0;
                   while ((count = input.read(data)) != -1) {
                      total += count;
                      int xc = (int) ((total * 100) / lenghtOfFile);

                      output.write(data, 0, count);
                      imgs.get(position).setProgress(xc);
                      notifyItemChanged(position);
                      try {
                          Thread.sleep(20);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              } finally {
               output.flush();
               output.close();
               input.close();
              }
        } catch (IOException e) {
           e.printStackTrace();
        }
      } 
     t1.start();
    }
}

Thats my guess, good luck!