1

EDIT2: ich es in der Bedingung explizit gemacht, wenn holder.showTaskRecyclerViewfalse ist die Ansicht zu verstecken, um explizit beide true abzudecken und false Fälle in onBindViewHolder. Ich habe immer noch das gleiche Problem.onBindViewHolder (VH, Position) nicht ordnungsgemäß die alten und neuen ViewHolder Kopien aufrufen, wenn notifyItemChanged mit()

EDIT1: Ich sollte hinzufügen, dass das Ein- und Ausblenden von tasksRecyclerView funktioniert gut, wenn ich notifyDataSetChanged() verwenden, statt notifyItemChanged(), aber dies deaktiviert die Animation und es ist teurer.

Ich habe eine RecyclerView namens tasksRecyclerView in meinem ViewHolder, die angezeigt und ausgeblendet werden soll, wenn auf die Ansicht geklickt wird. (Dies ist eine RecyclerView innerhalb des Haupt RecyclerView, so zu sagen.):

public class ViewHolder extends RecyclerView.ViewHolder { 
    public ImageView routineStateImgView; 
    public TextView alarmTextView; 
    public TextView routineNameTextView; 
    public RecyclerView tasksRecyclerView; 
    public boolean showTaskRecyclerView = false; 

    public ViewHolder(View routineItemView){ 
     super(routineItemView); 

     routineItemView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       //toggle showing TaskRecyclerView 
       showTaskRecyclerView = !showTaskRecyclerView; 
       notifyItemChanged(getAdapterPosition()); 
      } 
     }); 
     routineStateImgView = (ImageView) routineItemView.findViewById(R.id.routineStateImgView); 
     alarmTextView = (TextView) routineItemView.findViewById(R.id.alarmTextView); 
     routineNameTextView = (TextView) routineItemView.findViewById(R.id.routineNameTextView); 
     tasksRecyclerView = (RecyclerView) routineItemView.findViewById(R.id.tasksRecyclerView); 
    } 

    public ImageView getRoutineStateImgView() { 
     return routineStateImgView; 
    } 
    public TextView getAlarmTextView(){ 
     return alarmTextView; 
    } 
    public TextView getRoutineNameTextView(){ 
     return routineNameTextView; 
    } 
    public RecyclerView getTasksRecyclerView(){ 
     return tasksRecyclerView; 
    } 
} 

Derzeit ist die onClick im Code festgelegt ist, eine Variable wechseln (showTaskRecyclerView) innerhalb des ViewHolder definiert und dann notifyItemChanged(getAdapterPosition()) rufen Sie den Artikel aktualisieren Ändern Sie mit einer Animation.

Wenn OnBindViewHolder aufgerufen wird, prüft er den Zustand des ein- und Variable (showTaskRecyclerView, wieder einmal) und Häute oder blendet die RecyclerView auf der Variablen basiert. Sie können mit der Log.d Methode in diesem Snippet nach der Zeile diese Logik im Code sehen:

public void onBindViewHolder(RoutinesRecyclerViewAdapter.ViewHolder holder, int position) { 
    //Replace contents of view with data from item in adapterRoutinesList at position. 
    Routine routine = adapterRoutinesList.get(position); 
    TasksRecyclerViewAdapter mTasksRecyclerViewAdapter = null; 

    if(routine == null){ 
     holder.getRoutineStateImgView().setImageResource(android.R.color.transparent); 
     holder.getAlarmTextView().setText(""); 
     holder.getRoutineNameTextView().setText(""); 
     holder.getTasksRecyclerView().setVisibility(View.GONE); 
    }else{ 
     DateFormat dayTimeFormat = new SimpleDateFormat("HH:mm", Locale.US); 
     String dayTimeString = dayTimeFormat.format(routine.getWakeupTime().getTime()); 
     holder.getAlarmTextView().setText(dayTimeString); 
     holder.getRoutineNameTextView().setText(routine.getName()); 
     if(routine.getEnableRoutine()) { 
      holder.getRoutineStateImgView().setImageResource(R.drawable.check_mark); 
     } 
     else{ 
      holder.getRoutineStateImgView().setImageResource(R.drawable.x_mark); 
     } 

     Log.d(TAG, "position: " + position + " holder: " + holder + " show?: " + holder.showTaskRecyclerView); 
     if(holder.showTaskRecyclerView) { 
      TasksManager mTasksManager = adapterTasksListCache.get(routine.getId()); 
      if (mTasksManager == null) { 
       mTasksManager = new TasksManager(routine.getId()); 
       mTasksManager.readTasksFromDisk(mContext); 
       adapterTasksListCache.put(routine.getId(), mTasksManager); 
      } 

      mTasksRecyclerViewAdapter = adapterTasksViewCache.get(routine.getId()); 
      if (mTasksRecyclerViewAdapter == null) { 
       mTasksRecyclerViewAdapter = new TasksRecyclerViewAdapter(
         mContext, 
         position, 
         mTasksManager.getTasksListFromCache(), 
         mRequestImageCaptureCallBack, 
         mTaskEditTextListener); 
       adapterTasksViewCache.put(routine.getId(), mTasksRecyclerViewAdapter); 
      } 
      RecyclerView.LayoutManager mTaskLayoutManager = new LinearLayoutManager(mContext); 
      holder.getTasksRecyclerView().setLayoutManager(mTaskLayoutManager); 
      holder.getTasksRecyclerView().setAdapter(mTasksRecyclerViewAdapter); 
      holder.getTasksRecyclerView().setHasFixedSize(true); 
      holder.getTasksRecyclerView().setVisibility(View.VISIBLE); 
     } 
     else{ 
      holder.getTasksRecyclerView().setVisibility(View.GONE); 
     } 
    } 
} 

Ich erwarte, dass auf jedem Klick die RecyclerView ein- oder ausblenden, um zu sehen. Allerdings sehe ich nur das Verstecken/Einblenden-Verhalten nach jeweils 2 Klicks.

hide-unhide-with-2-clicks

Hier ist die Ausgabe des Log.d nach 5 Mal klicken:

04-16 21:33:37.026 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false 
04-16 21:33:42.626 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false 
04-16 21:33:44.511 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true 
04-16 21:33:46.274 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true 
04-16 21:33:47.938 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false 
04-16 21:41:52.756 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false 

Meine Interpretation ist, dass für die Übergangsanimation Zwecke verwendet notifyItemChanged die Verwendung von 2 Kopien des gleichen ViewHolder fordert (eins mit dem alten Zustand der Ansicht und eins mit dem neuen). Die Kopie mit der Variablen ändert sich jedoch fälschlicherweise in der alten Kopie. Ich nehme an, ich habe ein falsches Verständnis davon, wie notifyItemChanged funktioniert so ich hergekommen, um Hilfe:/

Auch

, ich habe keine Ahnung, was das Problem verursacht, wenn ich wirklich schnell klicken: Ich sehe keine Änderung, wenn ich schnell klicken genug (etwa so schnell wie weniger als eine halbe Sekunde)

die logcat zeigt folgende:

04-16 21:43:54.597 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true 
04-16 21:43:54.862 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 scrap [changeScrap] tmpDetached not recyclable(1) no parent} show?: true 
04-16 21:43:55.387 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true 
04-16 21:43:55.668 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 scrap [changeScrap] tmpDetached not recyclable(1) no parent} show?: true 
04-16 21:43:55.949 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true 
04-16 21:43:56.189 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 scrap [changeScrap] tmpDetached not recyclable(1) no parent} show?: true 
04-16 21:43:56.479 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true 

Irgendwelche Ideen?

Antwort

0

Ich habe um das Problem herum gearbeitet, indem ich ein ListArray außerhalb der ViewHolder mit einem showTaskRecyclerView für jedes Element im Adapter definiert.

Auf diese Weise werden sowohl die alten und neuen ViewHolder suchen auf der gleichen, einzigen showTaskRecyclerView pro Stück und nicht 2 unsynchronisierte showTaskRecyclerView pro Stück in beiden ViewHolder wohnen.

0

Sie müssen die Logik für die Bedingung implementieren, wenn holder.showTaskRecyclerViewfalse ist.

Die View behalten ihren Status und daher müssen Sie sie explizit ändern. Platziere eine Logik, um dich dort zu verstecken und überprüfe, ob es funktioniert.

+0

Von meinem Verständnis, die Recyclerview erhält einen Null-Adapter, wenn ich es "verstecken" will. Der Adapter "mTasksRecyclerViewAdapter" ist standardmäßig auf null festgelegt. Wenn ich zu der Bedingung komme, in der "halter.showTaskRecyclerView" wahr ist, wird der Adapter gesetzt. Das Hinzufügen einer else-Klausel bedeutet also nichts in der Logik. Wenn Sie sich die vorletzte Codezeile im zweiten Snippet ansehen, wird der Adapter der Ansicht immer auf einen Wert gesetzt, entweder auf null oder auf einen abgerufenen Adapter. – Cesar

+0

'View' werden recycelt und so den Zustand erhalten. Hier ist ein einfaches Beispiel, das dieses Problem veranschaulicht. http://pastie.org/private/ftgz5lnnlcjch8yqs1jyzq Haben Sie versucht, schleudern? Möglicherweise sehen Sie Probleme. Wenn beide Seiten der Logik nicht vorhanden sind, wird die Daten nicht ordnungsgemäß ungültig oder neu gebunden. – razzledazzle

+0

Yeah Schleudern funktioniert gut. Ich implementiere auch beide Seiten der Logik explizit (ich habe meinen Beitrag bearbeitet, um den neuen Code zu zeigen), aber das Problem tritt immer noch auf. – Cesar