Почему не работает notifyItemChanged

Понимаю что возможно глупый вопрос но не могу найти на него ответ. Прошу вашей помощи.

У меня есть RecyclerView, использующий LinearLayoutManager, и собственный RecyclerView.Adapter.

Мой класс данных:

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

    ... getters and setters...
}

Код в действии:

    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);

и адаптер:

    @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();
            }
        }
  });

Почему notifyItemChanged (position) срабатывает только после завершения операции и в TextView (txt) передается только значение 100?

UPD: этот код не работает

@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: этот код не работает

@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;
}

person SmallSani    schedule 15.12.2016    source источник
comment
прежде всего, удалите все финальные модификаторы и передайте их в тегах в представлениях   -  person Omar HossamEldin    schedule 18.12.2016
comment
@OmarHossamEldin Пример, пожалуйста   -  person SmallSani    schedule 19.12.2016


Ответы (1)


По сути, вы выполняете загрузку файла в поток пользовательского интерфейса, поэтому каждый раз, когда вы вызываете notifyItemChanged(), вы добавляете задачу в Looper, но Looper переходит к этой задаче только тогда, когда вы заканчиваете загрузку, поэтому вы видите только 100.

Я бы запустил загрузку в другом потоке, например:

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();
    }
}

Это мое предположение, удачи!

person Fashizel    schedule 18.12.2016