android RecyclerView метод notifyDataSetChange вызывает изменение всех элементов при нажатии на конкретный элемент - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть RecyclerView в моем проекте, который показывает список сообщений о билетах.Я использую нумерацию страниц, чтобы показать сообщения по частям.Я думаю, что notifyDataSetChange - это метод, который я должен использовать для добавления новых добавленных элементов.

Ниже приведен код для обработки добавления новых элементов в мой список:

public void makeList(List<SingleTicketModel> ticketMessages) {

    for (int i = 0; i < ticketMessages.size(); i++) {
        ticket.add(
                new TicketItemModel(
                        ticketMessages.get(i).getContent(),
                        ticketMessages.get(i).getCreatedAt(),
                        ticketMessages.get(i).getDirection(),
                        ticketMessages.get(i).getAgentName(),
                        ticketMessages.get(i).getAttachment()
                )

        );
    }
    if (ticketAdaptor == null) {
        ticketAdaptor = new TicketAdaptor(getApplicationContext(), ticket, this);
        recyclerView.setAdapter(ticketAdaptor);
        linearLayoutManager = new LinearLayoutManager(getApplicationContext());
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setVisibility(View.VISIBLE);
        recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(linearLayoutManager) {
            @Override
            public void onLoadMore(int current_page) {
                loadMoreProgressBar.setVisibility(View.VISIBLE);
                getTickets(loginToken, current_page,ticketID);
            }
        });
        progressBar.setVisibility(View.GONE);


    } else {

        ticketAdaptor.notifyDataSetChanged();

    }

Возможно, есть вложениев некоторых сообщениях и вот моя проблема:

Когда пользователь нажимает кнопку вложения, кнопка преобразуется в индикатор выполнения, пока вложение загружается.

Но если пользователь нажимаетна значке вложений все значки вложений в списке превращаются в progressBar, и это означает, что метод setOnClickListener выполняется для всех элементов!

Важно то, что это происходит, только если вызывается метод notifyDataSetChange.

Я делаю вывод, что если количество сообщений невелико и нет необходимости загружать дополнительную информацию, этого не произойдет.

Кроме того, еще один момент, который, на мой взгляд, связан с этой проблемой:

Если пользователь нажимает кнопку вложения (в этом случае изображение imageButton изменяется после завершения загрузкиe), кажется, что элемент будет восстановлен путем прокрутки списка, и изображение кнопки вложения вернется в первое состояние. (снова после добавления новых данных в список)

вот мой файл адаптера:

public class TicketAdaptor extends RecyclerView.Adapter<TicketAdaptor.ViewHolder> {

private Context context;
private Activity activity;
private List<TicketItemModel> ticket;
View view;

public TicketAdaptor(Context context, List<TicketItemModel> ticket, Activity activity){

    this.context = context;
    this.ticket = ticket;
    this.activity = activity;

}


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {



        this.view = LayoutInflater.from(this.context).inflate(R.layout.ticket_item_in, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    holder.ticketDescription.setText(ticket.get(position).getContent());
    holder.ticketDate.setText(ticket.get(position).getCreatedAt());
    switch (holder.getItemViewType()){

        case 1 :
            holder.itemView.setBackgroundResource(R.drawable.radius_background_gray);
            holder.ticketDate.setBackgroundResource(R.drawable.radius_background_light_gray);
            holder.ticketStatus.setImageResource(R.drawable.ic_attachment_black_24dp);
            break;
        case 11 :
            holder.itemView.setBackgroundResource(R.drawable.radius_background_gray);
            holder.ticketDate.setBackgroundResource(R.drawable.radius_background_light_gray);
            break;
        case 3 :
            holder.ticketStatus.setImageResource(R.drawable.ic_attachment_black_24dp);
            break;
        default: break;

    }
    holder.ticketTitle.setText(ticket.get(position).getAgentName() + " said :");

    holder.ticketStatus.setOnClickListener(new View.OnClickListener() {
        boolean counter = false;
        @Override
        public void onClick(View v) {
            if (requestPermission() == true) {
                File attachmentFile = new File((Environment.getExternalStorageDirectory()
                        + "/"
                        + context.getResources().getString(R.string.app_name)
                        + "/"
                        + context.getResources().getString(R.string.ticket_directory)
                        + "/"
                        + ticket.get(position).getCreatedAt().replaceAll("\\s|:|-","") + ".jpeg" ));

                if( !counter && !attachmentFile.exists())
                {
                    holder.attachmentProgressBar.setVisibility(View.VISIBLE);
                    holder.ticketStatus.setVisibility(View.GONE);
                    downloadAttachment(ticket.get(position)
                                    .getAttachment(),
                            ticket
                                    .get(position)
                                    .getCreatedAt()
                                    .replaceAll("\\s|:|-","") + ".jpeg",
                            holder.ticketStatus,holder.attachmentProgressBar);
                         counter = true;
                }else{
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_VIEW);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    File file = new File((Environment.getExternalStorageDirectory()
                            + "/"
                            + context.getResources().getString(R.string.app_name)
                            + "/"
                            + context.getResources().getString(R.string.ticket_directory)),
                             ticket.get(position).getCreatedAt().replaceAll("\\s|:|-","")
                            + ".jpeg"
                    );
                    intent.setDataAndType(FileProvider.getUriForFile(context,
                            BuildConfig.APPLICATION_ID + ".provider",
                            file),"image/*");
                    activity.startActivity(intent);
                }
            }


        }
    });

}

@Override
public int getItemViewType(int position) {
    String Direction = ticket.get(position).getDirection();
    String Attachment = ticket.get(position).getAttachment();
    if(Direction.equals("out")){
        if (Attachment != null)
            return 1;
        else return 11;
    }else if(!(Direction.equals("out"))){
        if(Attachment != null)
            return 3;
    }
    return 0;
}

@Override
public int getItemCount() {
    return ticket.size();
}


class ViewHolder extends RecyclerView.ViewHolder{

    TextView ticketTitle;
    TextView ticketDescription;
    TextView ticketDate;
    ImageView ticketStatus;
    ProgressBar attachmentProgressBar;

    public ViewHolder(View itemView) {
        super(itemView);
        this.ticketTitle = itemView.findViewById(R.id.ticket_agent);
        this.ticketDescription = itemView.findViewById(R.id.ticket_description);
        this.ticketDate = itemView.findViewById(R.id.ticket_date);
        this.ticketStatus = itemView.findViewById(R.id.ticket_attachment);
        this.attachmentProgressBar = itemView.findViewById(R.id.attachment_progressbar);
        attachmentProgressBar.setVisibility(View.GONE);
    }

}

private void downloadAttachment(String url, final String imageName, final View attachmentIcon, final View attachmentProgressBar){

    APIInterface apiInterface = APIClient.getClient().create(APIInterface.class);
    Call<ResponseBody> call = apiInterface.getAttachment(url);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            saveAttachment saveAttachment = new saveAttachment(imageName,attachmentIcon, attachmentProgressBar);
            saveAttachment.execute(response.body().byteStream());
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {

        }
    });


}

private class saveAttachment extends AsyncTask<InputStream,Void,Boolean>{

    private  String imageName;
    private View attachmentIcon;
    private View attachmentProgressBar;

    public saveAttachment(String imageName, View attachmentIcon, View attachmentProgressBar) {
        super();
        this.imageName = imageName;
        this.attachmentIcon = attachmentIcon;
        this.attachmentProgressBar = attachmentProgressBar;
    }

    @Override
    protected Boolean doInBackground(InputStream... inputStreams) {
        InputStream inputStream = inputStreams[0];
        final File directory = new File((Environment.getExternalStorageDirectory()
                + "/"
                + context.getResources().getString(R.string.app_name)
                + "/"
                + context.getResources().getString(R.string.ticket_directory)
        ));
        if (!directory.exists())
            directory.mkdirs();
        final File myImageFile = new File(directory, imageName);
        OutputStream outputStream = null;
        try {

            outputStream = new FileOutputStream(myImageFile);
            byte [] buffer = new byte[2048];
            int read;
            while ((read = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, read);
            }
            outputStream.flush();
            outputStream.close();
        }catch (IOException e){}
        return null;
    }

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

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        attachmentProgressBar.setVisibility(View.GONE);
        ((ImageView) attachmentIcon).setImageResource(R.drawable.ic_slow_motion_video_black_24dp);
        attachmentIcon.setVisibility(View.VISIBLE);

    }
}

}

(я удалил часть кода, не относящегося к теме.)

1 Ответ

0 голосов
/ 19 сентября 2018

Я не уверен, но это может быть проблемой из-за несовпадения позиций, так как вы добавляете больше в список.Я бы предложил установить свой OnClickListener в конструкторе ViewHolder.Параметр position в методе onBindViewHolder не должен рассматриваться как статический (при использовании в анонимных классах, таких как ваш слушатель).Посмотрите, станет ли все лучше.

Кроме того, вы можете использовать notifyItemChanged, чтобы просто поменять нажатие, например:

notifyItemChanged(getAdapterPosition());

внутри обратного вызова прослушивателя щелчков.

Итак, вашкод будет выглядеть примерно так:

public ViewHolder(View itemView) {
    super(itemView);
    this.ticketTitle = itemView.findViewById(R.id.ticket_agent);
    this.ticketDescription = itemView.findViewById(R.id.ticket_description);
    this.ticketDate = itemView.findViewById(R.id.ticket_date);
    this.ticketStatus = itemView.findViewById(R.id.ticket_attachment);
    this.attachmentProgressBar = itemView.findViewById(R.id.attachment_progressbar);
    attachmentProgressBar.setVisibility(View.GONE);
    ticketStatus.setOnClickListener(new View.OnClickListener() {
    boolean counter = false;
    @Override
    public void onClick(View v) {
        if (requestPermission() == true) {
            File attachmentFile = new File((Environment.getExternalStorageDirectory()
                    + "/"
                    + context.getResources().getString(R.string.app_name)
                    + "/"
                    + context.getResources().getString(R.string.ticket_directory)
                    + "/"
                    + ticket.get(getAdapterPosition()).getCreatedAt().replaceAll("\\s|:|-","") + ".jpeg" ));

            if (!counter && !attachmentFile.exists()) {
                attachmentProgressBar.setVisibility(View.VISIBLE);
                ticketStatus.setVisibility(View.GONE);
                downloadAttachment(ticket.get(getAdapterPosition()).getAttachment(),
                        ticket.get(getAdapterPosition()).getCreatedAt().replaceAll("\\s|:|-","") + ".jpeg",
                        ticketStatus, attachmentProgressBar);
                counter = true;
                // Update UI only for this item.
                notifyItemChanged(getAdapterPosition());
            } else {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                File file = new File((Environment.getExternalStorageDirectory()
                        + "/"
                        + context.getResources().getString(R.string.app_name)
                        + "/"
                        + context.getResources().getString(R.string.ticket_directory)),
                        ticket.get(getAdapterPosition()).getCreatedAt().replaceAll("\\s|:|-","")
                                + ".jpeg"
                );
                intent.setDataAndType(FileProvider.getUriForFile(context,
                        BuildConfig.APPLICATION_ID + ".provider",
                        file),"image/*");
                activity.startActivity(intent);
            }
        }
    }
    });
...