ViewPager2 onBindViewHolder funktioniert nicht richtig

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • ViewPager2 onBindViewHolder funktioniert nicht richtig

    Moin,

    ich habe in dem ViewPager2 mit TabLayout einen Recyclerview. Um in den die Daten einzuspeisen benutze ich einen Adapter (ViewPagerAdapter). Sobald die Daten in dem RecyclerView drin sind, ist die Interaktion mit den Daten kein Problem. Problematisch wird aber die erste Ebene, der richtige Umgang mit dem ViewPagerAdapter. Wenn ich in der tabbed Ansicht bin und den Tab wechsel, wird sofort der Adapter für die restlichen Tabs erzeugt und die Daten werden nur auf dem letzten Tab aktualisiert.

    Hier ist meine Activity, die den ViewPagerAdapter implementiert;

    Java-Quellcode

    1. public class AudioFilePanel extends AppCompatActivity
    2. {
    3. public static final int FILE_BROWSER_REQUEST_CODE = 1;
    4. private String currentTab;
    5. private ViewPagerAdapter adapter;
    6. private ViewPager2 viewPager;
    7. private Map<String, List<FileElement>> content;
    8. @Override
    9. protected void onCreate(Bundle savedInstanceState)
    10. {
    11. super.onCreate(savedInstanceState);
    12. setContentView(R.layout.activity_audio_file_panel);
    13. viewPager = findViewById(R.id.view_pager2);
    14. TabLayout tabLayout = findViewById(R.id.tabs);
    15. Button addFilesByTag = findViewById(R.id.add_files_with_tag);
    16. if (null == currentTab)
    17. {
    18. currentTab = "music";
    19. }
    20. content = listByTag();
    21. adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()), currentTab);
    22. viewPager.setAdapter(adapter);
    23. new TabLayoutMediator(tabLayout, viewPager,
    24. (tab, position) -> tab.setText(content.keySet().toArray()[position].toString())).attach();
    25. tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
    26. {
    27. @Override
    28. public void onTabSelected(TabLayout.Tab tab)
    29. {
    30. currentTab = tab.getText().toString();
    31. }
    32. @Override
    33. public void onTabUnselected(TabLayout.Tab tab)
    34. {
    35. }
    36. @Override
    37. public void onTabReselected(TabLayout.Tab tab)
    38. {
    39. }
    40. });
    41. addFilesByTag.setOnClickListener(l ->
    42. {
    43. Intent fileBrowser = new Intent(AudioFilePanel.this, FileBrowser.class);
    44. startActivityForResult(fileBrowser, 1);
    45. });
    46. }
    47. private void updateViweData()
    48. {
    49. content = listByTag();
    50. adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()), currentTab);
    51. viewPager.setAdapter(adapter);
    52. }
    53. private Map<String, List<FileElement>> listByTag()
    54. {
    55. Map<String, List<FileElement>> result = new HashMap<>();
    56. DirectoryDao dao = new DirectoryDao(getApplicationContext());
    57. String[] categories = {"music", "ambience", "effect"};
    58. for (String category : categories)
    59. {
    60. List<FileElement> directories =
    61. dao.getDirectoriesForCategory(category).stream().map(f -> new FileElement( new File(f.getPath()).getName(), f.getPath(), true)).collect(Collectors.toList());
    62. result.put(category, directories);
    63. }
    64. return result;
    65. }
    66. @Override
    67. protected void onActivityResult(int requestCode, int resultCode, Intent data)
    68. {
    69. super.onActivityResult(requestCode, resultCode, data);
    70. if (resultCode == RESULT_OK && requestCode == FILE_BROWSER_REQUEST_CODE)
    71. {
    72. String path = data.getStringExtra("path");
    73. storeDirectory(path, data.getBooleanExtra("includeSubdirs", true), currentTab);
    74. updateViweData();
    75. }
    76. }
    77. private void storeDirectory(String path, boolean recursive, String tag)
    78. {
    79. Directory directory = new Directory();
    80. directory.setPath(path);
    81. directory.setTag(tag);
    82. directory.setRecursive(recursive);
    83. DirectoryDao dao = new DirectoryDao(getApplicationContext());
    84. directory.setId(dao.insert(directory));
    85. }
    86. }
    Alles anzeigen



    Das ist der ViewPagerAdapter:
    Beim debuggen habe ich rausgefunden, dass beim ersten Tabwechsel (danach nicht mehr) direkt der onBindViewHolder ausgeführt wird.

    Quellcode

    1. public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.ViewHolder>
    2. {
    3. private static final String PREVIOUS_DIRECTORY = "previous directory";
    4. private List<List<FileElement>> filesListsByCategory;
    5. private LayoutInflater mInflater;
    6. private Context ctx;
    7. private ItemListAdapter adapter;
    8. private String rootPath;
    9. private List<FileElement> rootElements;
    10. private String tag;
    11. public ViewPagerAdapter(Context context, List<List<FileElement>> data, String tag)
    12. {
    13. this.mInflater = LayoutInflater.from(context);
    14. this.filesListsByCategory = data;
    15. this.ctx = context;
    16. this.tag = tag;
    17. rootElements = new ArrayList<>(filesListsByCategory.get(0));
    18. }
    19. @NotNull
    20. @Override
    21. public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType)
    22. {
    23. return new ViewHolder(mInflater.inflate(R.layout.item_viewpager, parent, false));
    24. }
    25. @Override
    26. public void onBindViewHolder(ViewHolder holder, int position)
    27. {
    28. FileBrowserService fbs = new FileBrowserService();
    29. List<FileElement> categoryFiles = new ArrayList<>(filesListsByCategory.get(position));
    30. adapter = new ItemListAdapter(categoryFiles, item -> handleClickOnElement(fbs, item));
    31. holder.myView.setAdapter(adapter);
    32. }
    33. private void handleClickOnElement(FileBrowserService fbs, FileElement item)
    34. {
    35. if (new File(item.getPath()).isDirectory())
    36. {
    37. List<FileElement> newContent;
    38. String newPath;
    39. if (item.isRoot())
    40. {
    41. rootPath = item.getPath();
    42. }
    43. if (PREVIOUS_DIRECTORY.equals(item.getName()))
    44. {
    45. newPath = item.getPath().substring(0, item.getPath().lastIndexOf('/'));
    46. } else
    47. {
    48. newPath = item.getPath();
    49. }
    50. FileElement goToParent = new FileElement(PREVIOUS_DIRECTORY, newPath, false);
    51. if (item.getPath().equals(rootPath) && !item.isRoot())
    52. {
    53. newContent = rootElements;
    54. } else
    55. {
    56. newContent = fbs.getFiles(newPath);
    57. newContent.add(0, goToParent);
    58. }
    59. updateListElements(newContent);
    60. } else
    61. {
    62. //TODO: play track
    63. }
    64. }
    65. private void updateListElements(List<FileElement> newContent)
    66. {
    67. adapter.updateData(null, "clearData");
    68. adapter.updateData(newContent, "updateData");
    69. }
    70. @Override
    71. public int getItemCount()
    72. {
    73. return filesListsByCategory.size();
    74. }
    75. class ViewHolder extends RecyclerView.ViewHolder
    76. {
    77. RecyclerView myView;
    78. RelativeLayout relativeLayout;
    79. ViewHolder(View itemView)
    80. {
    81. super(itemView);
    82. myView = itemView.findViewById(R.id.my_list);
    83. myView.setLayoutManager(new LinearLayoutManager(ctx));
    84. relativeLayout = itemView.findViewById(R.id.container);
    85. }
    86. }
    87. }
    Alles anzeigen

    Das Endeffekt sieht so aus:

    gifyu.com/image/qVjy

    Hat jemand eine Idee wie man den ViewPagerAdapter anbinden muss oder was ich falsch mache?

    (Es ist für mich sehr wichtig die Antworten zu erklären, denn ich möchte eine Lösung, aber ich möchte es auch verstehen)
  • Wenn ich in der tabbed Ansicht bin und den Tab wechsel, wird sofort der Adapter für die restlichen Tabs erzeugt und die Daten werden nur auf dem letzten Tab aktualisiert.

    Das ist das Normale Verhalten eines Viewpager. Es werden immer die Nachbar Layouts vorgeladen. Damit sie beim Swype auch schon angezeigt werden können. denn es gibt ja einen Moment wo beider Fragmente zu hälfte sichtbar sind. Somit muss das Layout auch schon im Speicher sein.
    Beim sichtbar werden des Fragments wird nicht die onCreateView durchlaufen.
    Beim sichtbar werden, werden die Nachbar Fragment durchlaufen und in den Speicher geladen.
    Ein Feedback auf Tipps ist auch schön. :P
  • Hallo dazu solltest du dir mal das ViewModel Modell anschauen.
    developer.android.com/topic/li…3d5QqOEAAYASAAEgK5S_D_BwE
    hier ein einfaches Beispiel was auf der Grundlage des vom Studio erstellten Bottom Menu beruht.
    Ich habe nur in dem Dashboard Fragment ein Edittext und Button hinzugefügt der in das MainViewModel schreibet.
    Im Noti Fragment habe ich eine Textview hinzugefügt die den Inhalt aus dem MainViewModel liest und in dem Text anzeigt.
    Beachte das du beim zugriff auf die ViewModels immer den richtigen Kontext brauchst.
    Dateien
    • BottomTab2.zip

      (507,25 kB, 77 mal heruntergeladen, zuletzt: )
    Ein Feedback auf Tipps ist auch schön. :P
  • winterrmute schrieb:

    Mir ist nur immer noch nicht klar, warum die results von dem ersten Tab auf dem dritten Tab angezeigt werden. Und umgekehrt
    das solltest du nochmal genauer erlären und zeigen.


    In deinem video .

    Sieht es genau so aus wie ich es beschrieben habe.

    Du bist in tab 1 wählt etwasaus und willst das an das Nachbar Fragment übergeben. Das nimmt es nicht da die onCrateView nicht durchlaufen wird.

    Du bist in Tab 1 machst eine Auswahl und willst das an Tab 3 übergeben da Tab3 kein direkter Nachbar ist wird wohl die onCrateView durchlaufen und der Intent auch ausgewertet. Da nach dem sichtbar werden des tab 3 die Nachbarn wieder neu geladen werden, wird wohl erst jetzt die Änderungen die du am Tab 2 gemacht hast angenommen da jetzt die onCreatvie von tab 2 aufgerufen wird. Aber angezeigt wird 3.

    das ist ob du es glaubst oder nicht ein klassisches verhalten vom viewpager.


    androidwave.com/android-viewpager-with-tabs/
    tausiq.wordpress.com/2014/06/0…ck-in-each-viewpager-tab/
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von jogimuc ()