0

recyclerview에서 선택한 항목의 상태를 설정하려고합니다. UI는 단일 셀 framelayout 하나 drawable xml의 배경을 다른 셀로 변경하여 수행합니다. 다음Drawable Recyclerview 배경 변경 느리게, 주 스레드에서 너무 많은 작업을 수행하는 중 오류가 발생했습니다.

@Override 
    public void onBindViewHolder(final DeviceAlarmTonesHolder holder, final int position) { 
     final DeviceAlarmTone alarmTone = alarmTones.get(position); 
     // set click listener 
     holder.itemView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

       holder.alarmTonesButtonBackground.setBackgroundResource(R.drawable.layout_bg_selected); 
       itemClickListener.onItemClicked(holder, alarmTone, position, oldPostion); 

       // Refresh the ui for the previous button 
       if (oldPostion != -1){ 
        notifyItemChanged(oldPostion); 
       } 
       oldPostion = position; 
      } 
     }); 


     String alarmToneString = alarmTones.get(position).getNotificationTitle(); 
     holder.alarmTonesNameTextView.setText(alarmToneString); 

    } 
현재 항목의 onclick을 내가 변화하고 배경에서 기본적으로

다시 선택 해제의 배경을 되돌릴 이전 항목 notifyitemchanged 부르심 다음 recyclerview에서

는이 같은 변화가 만들어 onBindViewHolder.

선택하지 않은 배경 :

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
    <solid android:color="#212121"/> 
    <corners android:radius="10dip"/> 
    <padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" /> 
</shape> 

선정 backgound에 : 당신의 도움에 미리

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
    <solid android:color="#0091EA"/> 
    <corners android:radius="10dip"/> 
    <padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" /> 
</shape> 

감사 변경되는

배경은 다음과 같이 XML을 드로어 블 있습니다. 난 그냥 문제가 거기에서 발생 여부를 확인하기 위해 이전 배경을 업데이트

public class DeviceAlarmToneAdapter extends RecyclerView.Adapter<DeviceAlarmTonesHolder>{ 

    Context context; 
    ArrayList<DeviceAlarmTone> alarmTones; 
    DeviceAlarmToneClickListener itemClickListener; 

    int oldPostion = -1; 

    public DeviceAlarmToneAdapter(Context context, ArrayList<DeviceAlarmTone> alarmTones, DeviceAlarmToneClickListener itemClickListener) { 
     this.context = context; 
     this.alarmTones = alarmTones; 
     this.itemClickListener = itemClickListener; 
    } 

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

     View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.singlecell_devicealarmtoneslist, parent, false); 
     DeviceAlarmTonesHolder holder = new DeviceAlarmTonesHolder(v, context); 
     return holder; 
    } 

    @Override 
    public void onBindViewHolder(final DeviceAlarmTonesHolder holder, final int position) { 
     final DeviceAlarmTone alarmTone = alarmTones.get(position); 
     // set click listener 
     holder.itemView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

       holder.alarmTonesButtonBackgroundUnselected.setVisibility(View.INVISIBLE); 
       holder.alarmTonesButtonBackgroundSelected.setVisibility(View.VISIBLE); 
       itemClickListener.onItemClicked(holder, alarmTone, position, oldPostion); 

       // Refresh the ui for the previous button 
       if (oldPostion != -1){ 
        notifyItemChanged(oldPostion); 
       } 
       oldPostion = position; 
      } 
     }); 


     String alarmToneString = alarmTones.get(position).getNotificationTitle(); 
     holder.alarmTonesNameTextView.setText(alarmToneString); 

    } 

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

} 
+0

뷰 유형에 따라보기 항목을 재활용 뷰의 유형을 확인하고 렌더링합니다. – Manikanta

+0

괜찮아요. bI 감사합니다. –

+0

전체 어댑터를 게시하십시오. –

답변

0
public class DeviceAlarmToneAdapter extends RecyclerView.Adapter<DeviceAlarmTonesHolder>{ 

Context context; 
ArrayList<DeviceAlarmTone> alarmTones; 
DeviceAlarmToneClickListener itemClickListener; 

int oldPostion = -1; 

public DeviceAlarmToneAdapter(Context context, ArrayList<DeviceAlarmTone> alarmTones, DeviceAlarmToneClickListener itemClickListener) { 
    this.context = context; 
    this.alarmTones = alarmTones; 
    this.itemClickListener = itemClickListener; 
} 

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

    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.singlecell_devicealarmtoneslist, parent, false); 
    DeviceAlarmTonesHolder holder = new DeviceAlarmTonesHolder(v, context); 
    return holder; 
} 

@Override 
public void onBindViewHolder(final DeviceAlarmTonesHolder holder, final int position) { 
    final DeviceAlarmTone alarmTone = alarmTones.get(position); 


    String alarmToneString = alarmTones.get(position).getNotificationTitle(); 
    holder.alarmTonesNameTextView.setText(alarmToneString); 

} 

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


public class DeviceAlarmTonesHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 

    // view fields are here 

    public DeviceAlarmTonesHolder(View itemView){ 
     super(itemView); 

     // find view by ids by using itemview.findViewById(id) 

     itemView.setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View view) { 
     // you shouldnt use two views as background objects to show unselected or selected background. Use selector drawables xml instead... and call view.setSelected(true or false); 
     // Since your modifyng view object itself you dont need to call notifyItemChanged... 
     // with this tecnique you have only one View.OnClickListener object which belongs to your holder that have only one instance. This will lower your memory usage and fluid scrolls. 

     if (itemClickListener != null){ 
      int position = getAdapterPosition(); 
      alarmTone = alarmTones.get(position); 

      itemClickListener.onAlarmClicked(alarmTone); 
     } 
    } 
} 

}

을 우회 :

UPDATE 여기 내 전체 어댑터입니다.

onBindHolder에서 프로세스를 낮추고 그 안에 개체를 생성하지 않아야합니다. 왜냐하면 스크롤 할 때마다 오래된 객체를 사용하는 대신 더 많은 객체를 생성하고 싶지 않기 때문입니다.

// 선택하지 않은 배경 또는 선택한 배경을 표시하기 위해 두 개의보기를 배경 개체로 사용하면 안됩니다. selector drawables xml 대신 ...을 사용하고 view.setSelected (true 또는 false)를 호출하십시오. 또한 배경을 최적화하십시오. 크기를 줄입니다. 당신을 위해 그것을 할 많은 온라인 도구가 있습니다. 다른 한편으로 jpegs와 pngs 같은 그림이 있다면 크기 조절을 제외하기 위해 drawable-nodpi 폴더에 넣습니다.

부터 당신이 notifyItemChanged를 호출 할 필요가없는 당신의 modifyng보기 개체 자체를 ... 당신은 하나의 인스턴스 만이 당신의 홀더에 속하는 하나의 View.OnClickListener 개체가이 tecnique으로

.

이렇게하면 메모리 사용량과 유동 스크롤이 줄어 듭니다.

문제가 발생하면 Single Choice RecyclerView 라이브러리를 사용하거나 다른 솔루션을 찾아야 할 수 있습니다. 모든 항목이 단순히 객체 유형을 확인하고 항목이 recyclerview의 위치를 ​​변경 전화 변경을 선택할 때마다 나는 당신에게 추천이

행운

+0

안녕하세요. Emre, 아이템을 선택 취소하라는 알림을받지 않았습니다. 그러나 내가 이전에 언급 한 바에 따르면 그 문제는 그보다 더 깊다. 클릭 리스너 및 모든 배경 드로어 블을 제거했지만 여전히 문제가 있습니다. http://stackoverflow.com/questions/40338467/gridview-scroll-slow-too-much-work-on-ui-thread-error –

+0

내 onBindHolder 메서드 및 ViewHolder 클래스로 시도해 주실 수 있습니까? 그것도 낮은 기회를 가지고있는 해결책이 될 수 있습니다 :) –

+0

나는 그것이 더 좋은 방법이라는 것을 이해합니다. 그리고 나는 그것을 원래의 질문에 대한 대답으로 받아 들일 것입니다. 그러나 그것을 고치는 기간에 문제는 그보다 더 깊지 않습니다. 도와 줘서 고마워. –