java - 如何用下一页填充标题和网格布局 "10 items"

标签 java android android-fragments android-recyclerview android-viewholder

在我的应用程序中,我有四种布局, 《卡片 list 》 , 《卡片杂志》 , 《标题》 《网格》 ,我制作选项菜单以允许用户从选项菜单“更改布局”中更改它,这里发生的问题是当第一次运行应用程序时选择标题或网格布局时,它显示唯一的第一页“10 个项目”结果来自改造电话
enter image description here
相关见此question
在这个应用程序的旧版本“当我使用 Activity 时”中,我用 Title 和 Grid Viewholder 上的这行代码解决了这个问题

if(position == getItemCount() -1)

if(context instanceof MainActivity){
 ((MainActivity)context).getMainPagePosts();

}
但是在这个版本中我使用了 fragment ,所以当我试图解决它时,我创建了一个名为 的界面“调用了哪个 fragment ”并给它 fragment 和viewHolder作为参数
public interface WhichFragmentCalled {

     void whichFragmentAndViewModel(Fragment fragment, PostViewModel postViewModel);
}

然后我像这样在适配器和 fragment 中使用它
 @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        WhichFragmentCalled whichFragmentCalled = adapter;

        whichFragmentCalled.whichFragmentAndViewModel(this,postViewModel);
    }
并让适配器实现这个接口(interface),这里是完整的后适配器 代码
public class PostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements WhichFragmentCalled{
    private Context context;
    private List<Item> items;

    private static final int CARD = 0;
    private static final int CARD_MAGAZINE = 1;
    private static final int TITLE = 2;
    private static final int GRID = 3;
    private static final int SDK_VERSION = Build.VERSION.SDK_INT;
    public static final String TAG = "POST ADAPTER";

    private int viewType;
    private int position;
    private Fragment fragment;
    private PostViewModel postViewModel;

    public PostAdapter(Context context, List<Item> items) {
        this.context = context;
        this.items = items;
    }

    public void setViewType(int viewType) {
        this.viewType = viewType;
        notifyDataSetChanged();
    }

    public int getViewType() {
        return this.viewType;
    }


    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view;

        if (this.viewType == CARD) {
            view = inflater.inflate(R.layout.card, parent, false);
            return new CardViewHolder(view);
        } else if (this.viewType == CARD_MAGAZINE) {
            view = inflater.inflate(R.layout.card_magazine, parent, false);
            return new CardMagazineViewHolder(view);
        } else if (this.viewType == TITLE) {
            if(SDK_VERSION < Build.VERSION_CODES.LOLLIPOP){
                view = inflater.inflate(R.layout.title_layout_v15,parent,false);
            }else {
                view = inflater.inflate(R.layout.title_layout, parent, false);
            }
            return new TitleViewHolder(view);
        } else {
            if(SDK_VERSION < Build.VERSION_CODES.LOLLIPOP){
                view = inflater.inflate(R.layout.grid_layout_v15,parent,false);
            }else {
                view = inflater.inflate(R.layout.grid_layout, parent, false);
            }
            return new GridViewHolder(view);
        }

    }


    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {


        this.position = position;


        int itemType = getViewType();
        Item item = items.get(holder.getAdapterPosition());
        final Document document = Jsoup.parse(item.getContent());
        final Elements elements = document.select("img");

//        Log.e("IMAGE", document.getAllElements().select("img").get(0).attr("src"));

        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat
                ("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
        Intent intent = new Intent(context, DetailsActivity.class);

        switch (itemType) {
            case CARD:
                if (holder instanceof CardViewHolder) {
                    CardViewHolder cardViewHolder = (CardViewHolder) holder;
                    cardViewHolder.postTitle.setText(item.getTitle());

                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(cardViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        cardViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }


                    cardViewHolder.postDescription.setText(document.text());
                    try {
                        date = format.parse(items.get(position).getPublished());

                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    PrettyTime prettyTime = new PrettyTime();

                    cardViewHolder.postDate.setText(prettyTime.format(date));

                    cardViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {


                            intent.putExtra("url", item.getUrl());
                            intent.putExtra("title", item.getTitle());
                            intent.putExtra("content", item.getContent());
                            int youtubeThumbnailImagesetVisibility = 0;

                            Element element = document.body();

                            String youtubeThumbnailImageSrc = "";
                            String youTubeLink = "";
                            for (Element e : element.getElementsByClass
                                    ("YOUTUBE-iframe-video")) {
                                youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                                youTubeLink = e.attr("src");
                                Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                                Log.e("Youtube link", youTubeLink);
                            }

                            if (youtubeThumbnailImageSrc.isEmpty()) {
                                youtubeThumbnailImagesetVisibility = 8;
                                intent.putExtra("youtubeThumbnailImagesetVisibility",
                                        youtubeThumbnailImagesetVisibility);
                            } else {
                                intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                                intent.putExtra("youTubeLink", youTubeLink);
                            }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                            view.getContext().startActivity(intent);
                        }
                    });
                }
                break;

            case CARD_MAGAZINE:
                if (holder instanceof CardMagazineViewHolder) {
                    CardMagazineViewHolder cardMagazineViewHolder = (CardMagazineViewHolder) holder;
                    cardMagazineViewHolder.postTitle.setText(item.getTitle());


                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(cardMagazineViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        cardMagazineViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }

                    try {
                        date = format.parse(items.get(position).getPublished());

                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    PrettyTime prettyTime = new PrettyTime();

                    cardMagazineViewHolder.postDate.setText(prettyTime.format(date));

                    cardMagazineViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            intent.putExtra("url", item.getUrl());
                            intent.putExtra("title", item.getTitle());
                            intent.putExtra("content", item.getContent());
                            int youtubeThumbnailImagesetVisibility = 0;

                            Element element = document.body();

                            String youtubeThumbnailImageSrc = "";
                            String youTubeLink = "";
                            for (Element e : element.getElementsByClass
                                    ("YOUTUBE-iframe-video")) {
                                youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                                youTubeLink = e.attr("src");
                                Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                                Log.e("Youtube link", youTubeLink);
                            }

                            if (youtubeThumbnailImageSrc.isEmpty()) {
                                youtubeThumbnailImagesetVisibility = 8;
                                intent.putExtra("youtubeThumbnailImagesetVisibility",
                                        youtubeThumbnailImagesetVisibility);
                            } else {
                                intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                                intent.putExtra("youTubeLink", youTubeLink);
                            }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                            view.getContext().startActivity(intent);
                        }
                    });
                }
                break;
            case TITLE:
                if (holder instanceof TitleViewHolder) {
                    TitleViewHolder titleViewHolder = (TitleViewHolder) holder;
                    titleViewHolder.postTitle.setText(item.getTitle());

                    Log.d("TITLE", "title layout called");


                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(titleViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        titleViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }


                    titleViewHolder.itemView.setOnClickListener(view -> {
                        intent.putExtra("url", item.getUrl());
                        intent.putExtra("title", item.getTitle());
                        intent.putExtra("content", item.getContent());
                        int youtubeThumbnailImagesetVisibility = 0;

                        Element element = document.body();

                        String youtubeThumbnailImageSrc = "";
                        String youTubeLink = "";
                        for (Element e : element.getElementsByClass
                                ("YOUTUBE-iframe-video")) {
                            youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                            youTubeLink = e.attr("src");
                            Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                            Log.e("Youtube link", youTubeLink);
                        }

                        if (youtubeThumbnailImageSrc.isEmpty()) {
                            youtubeThumbnailImagesetVisibility = 8;
                            intent.putExtra("youtubeThumbnailImagesetVisibility",
                                    youtubeThumbnailImagesetVisibility);
                        } else {
                            intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                            intent.putExtra("youTubeLink", youTubeLink);
                        }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                        view.getContext().startActivity(intent);
                    });

                }
                break;
            case GRID:
                if (holder instanceof GridViewHolder) {
                    GridViewHolder gridViewHolder = (GridViewHolder) holder;
                    gridViewHolder.postTitle.setText(item.getTitle());


                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(gridViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        gridViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }



                    gridViewHolder.itemView.setOnClickListener(view -> {
                        intent.putExtra("url", item.getUrl());
                        intent.putExtra("title", item.getTitle());
                        intent.putExtra("content", item.getContent());
                        int youtubeThumbnailImagesetVisibility;

                        Element element = document.body();

                        String youtubeThumbnailImageSrc = "";
                        String youTubeLink = "";
                        for (Element e : element.getElementsByClass
                                ("YOUTUBE-iframe-video")) {
                            youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                            youTubeLink = e.attr("src");
                            Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                            Log.e("Youtube link", youTubeLink);
                        }

                        if (youtubeThumbnailImageSrc.isEmpty()) {
                            youtubeThumbnailImagesetVisibility = 8;
                            intent.putExtra("youtubeThumbnailImagesetVisibility",
                                    youtubeThumbnailImagesetVisibility);
                        } else {
                            intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                            intent.putExtra("youTubeLink", youTubeLink);
                        }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                        view.getContext().startActivity(intent);
                    });
                }
        }
    }


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

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public void whichFragmentAndViewModel(Fragment fragment, PostViewModel postViewModel) {
        this.fragment = fragment;
        this.postViewModel = postViewModel;

        if(position == getItemCount() -1) {
           postViewModel.getPosts();
           notifyDataSetChanged();
        }
    }


    public class CardViewHolder extends RecyclerView.ViewHolder {

        ImageView postImage;
        TextView postTitle,postDescription, postDate;

        private CardViewHolder(View itemView) {
            super(itemView);
            postImage = itemView.findViewById(R.id.postImage);
            postTitle = itemView.findViewById(R.id.postTitle);
            postDescription = itemView.findViewById(R.id.postDescription);
            postDate = itemView.findViewById(R.id.postDate);

        }
    }

    public class CardMagazineViewHolder extends RecyclerView.ViewHolder {

        ImageView postImage;
        TextView postTitle, postDate;

        private CardMagazineViewHolder(View itemView) {
            super(itemView);
            postImage = itemView.findViewById(R.id.postImage);
            postTitle = itemView.findViewById(R.id.postTitle);
            postDate = itemView.findViewById(R.id.postDate);

        }
    }

    public class TitleViewHolder extends RecyclerView.ViewHolder {
        TextView postTitle;
        MyImageview postImage;


        private TitleViewHolder(@NonNull View itemView) {
            super(itemView);
            postTitle = itemView.findViewById(R.id.postTitle);
            postImage = itemView.findViewById(R.id.postImage);
        }
    }


    public class GridViewHolder extends RecyclerView.ViewHolder {
        TextView postTitle;
        MyImageview postImage;


        private GridViewHolder(@NonNull View itemView) {
            super(itemView);
            postTitle = itemView.findViewById(R.id.postTitle);
            postImage = itemView.findViewById(R.id.postImage);
        }
    }
}
现在此代码仅在我从标题或网格布局切换到其他布局并再次返回时才有效,我认为 onBindViewHolder 没有第一时间检测到这个接口(interface)的实现,所以挑战是如何将这个接口(interface)的实现移动到 onBindViewHolder 方法
 @Override
    public void whichFragmentAndViewModel(Fragment fragment, PostViewModel postViewModel) {
        this.fragment = fragment;
        this.postViewModel = postViewModel;

        if(position == getItemCount() -1) {
           postViewModel.getPosts();
           notifyDataSetChanged();
        }
    }
这就是我在 fragment 中使用更改布局的方式,我删除了与问题代码无关的
首页 fragment 类
private PostViewModel postViewModel;
    public static final String TAG = "HomeFragment";
    private RecyclerView recyclerView;
    private PostAdapter adapter;
    private List<Item> itemArrayList;

    private boolean isScrolling = false;
    private int currentItems, totalItems, scrollOutItems;
    private GridLayoutManager titleLayoutManager, gridLayoutManager;
    WrapContentLinearLayoutManager layoutManager;


    private SharedPreferences sharedPreferences;

    public ItemsDatabase itemsDatabase;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        postViewModel = new ViewModelProvider(this).get(PostViewModel.class);

        itemsDatabase = ItemsDatabase.getINSTANCE(getContext());

        postViewModel.finalURL.setValue(PostsClient.getBaseUrl() + "?key=" + PostsClient.getKEY() );

        postViewModel.getPosts();

        View root = inflater.inflate(R.layout.fragment_home, container, false);

        setHasOptionsMenu(true);

        itemArrayList = new ArrayList<>();

        recyclerView = root.findViewById(R.id.homeRecyclerView);
        adapter = new PostAdapter(getContext(),itemArrayList);


        layoutManager = new WrapContentLinearLayoutManager(getContext(),
                LinearLayoutManager.VERTICAL, false);
        titleLayoutManager = new GridLayoutManager(getContext(), 2);
        gridLayoutManager = new GridLayoutManager(getContext(), 3);

        sharedPreferences =  getContext().getSharedPreferences("settings", Context.MODE_PRIVATE);
        String layout = sharedPreferences.getString("recyclerViewLayout", "cardLayout");
        switch (layout) {
            case "cardLayout":
                recyclerView.setLayoutManager(layoutManager);
                adapter.setViewType(0);
                recyclerView.setAdapter(adapter);
                break;
            case "cardMagazineLayout":
                recyclerView.setLayoutManager(layoutManager);
                adapter.setViewType(1);
                recyclerView.setAdapter(adapter);
                break;
            case "titleLayout":
                recyclerView.setLayoutManager(titleLayoutManager);
                adapter.setViewType(2);
                recyclerView.setAdapter(adapter);
                adapter.whichFragmentAndViewModel(this,postViewModel);
                break;
            case "gridLayout":
                recyclerView.setLayoutManager(gridLayoutManager);
                adapter.setViewType(3);
                recyclerView.setAdapter(adapter);
                adapter.whichFragmentAndViewModel(this,postViewModel);


        }


        recyclerView.setAdapter(adapter);

  recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                    isScrolling = true;



            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (dy > 0) {
                    if(layout.equals("cardLayout") || layout.equals("cardMagazineLayout")) {
                        currentItems = layoutManager.getChildCount();
                        totalItems = layoutManager.getItemCount();
                        scrollOutItems = layoutManager.findFirstVisibleItemPosition();
                    }else if(layout.equals("titleLayout")){
                        currentItems = titleLayoutManager.getChildCount();
                        totalItems = titleLayoutManager.getItemCount();
                        scrollOutItems = titleLayoutManager.findFirstCompletelyVisibleItemPosition();
                    }else {
                        currentItems = gridLayoutManager.getChildCount();
                        totalItems = gridLayoutManager.getItemCount();
                        scrollOutItems = gridLayoutManager.findFirstCompletelyVisibleItemPosition();
                    }
                    if (isScrolling && (currentItems + scrollOutItems == totalItems)) {
                        isScrolling = false;
                        postViewModel.getPosts();
//                        adapter.notifyDataSetChanged();


                    }
                }

            }
        });


        return root;

    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        //Empty the old menu
//        if(menu.hasVisibleItems()){
//            menu.clear();
//        }
        inflater.inflate(R.menu.main, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        if (item.getItemId() == R.id.change_layout) {
            android.app.AlertDialog.Builder builder
                    = new android.app.AlertDialog.Builder(getContext());

            builder.setTitle(getString(R.string.choose_layout));

            String[] recyclerViewLayouts = getResources().getStringArray(R.array.RecyclerViewLayouts);
            SharedPreferences.Editor editor = sharedPreferences.edit();


            builder.setItems(recyclerViewLayouts, (dialog, index) -> {
                switch (index) {
                    case 0: // Card List Layout
                        adapter.setViewType(0);
                        recyclerView.setLayoutManager(layoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "cardLayout");
                        editor.apply();
                        break;
                    case 1: // Cards Magazine Layout
                        adapter.setViewType(1);
                        recyclerView.setLayoutManager(layoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "cardMagazineLayout");
                        editor.apply();
                        break;
                    case 2: // PostTitle Layout
                        adapter.setViewType(2);
                        recyclerView.setLayoutManager(titleLayoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "titleLayout");
                        editor.apply();
                        break;
                    case 3: //Grid Layout
                        adapter.setViewType(3);
                        recyclerView.setLayoutManager(gridLayoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "gridLayout");
                        editor.apply();

                }
            });

            android.app.AlertDialog alertDialog = builder.create();
            alertDialog.show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        WhichFragmentCalled whichFragmentCalled = adapter;

        whichFragmentCalled.whichFragmentAndViewModel(this,postViewModel);
    }
}

最佳答案

这更像是一个建议而不是一个答案,但是如果您要使用 ViewModel,我强烈建议您移动所有业务逻辑(几乎所有与 ui 无关的内容),并将其移动到您的 viewmodel 中。您可以从 android 站点阅读更多关于 MVVM 架构的信息。
至于你的实际问题,如果你只显示 10 个对象,那么听起来你的数据列表只有 10 个对象 - 所以我建议验证你从改造中收到的数据列表,然后在它传递给你的适配器时验证它。日志和/或断点将为您提供帮助。
另外,为了解释的简单,我会将所有代码移到 onCreateView() 中。出现在 setHasOptionsMenu(true); 之后并将其移至 onViewCreated()所以你不会意外有空 View 。然后我会将您所有的适配器/回收器 View 逻辑移动到 onResume()以便在配置/状态更改时正确恢复列表/用户界面。
如果 PostAdapter正在用于所有不同的布局,则不需要您的界面。您只需要一个 Fragment 类、一个 ViewModel 和一个 RecyclerView.Adapter,因为如果我理解正确,您使用的是相同的对象列表,因此您只需要专注于更改适配器的 View /布局即可。
要更改布局:

  • 通过将适配器的引用设置为 null,使回收器 View 中的当前可见列表无效。 recyclerView.setAdapter(null);
  • 创建适配器的新实例,如果您将数据集保存在 View 模型中,则可以将其传递给新适配器,而不是从改造中获取更多对象。
  • 然后,将新适配器设置回 recyclerView,并根据情况应用适当的 LayoutManager。
  • postViewModel.getPosts(); - 如果这是从改造加载帖子对象,那么这是另一个潜在的错误,因为改造通常是异步的,并且看起来你没有任何条件检查来确保你的列表在传递给适配器之前准备好。你可以用安卓轻松解决这个问题LiveData对象。它们很棒,非常适合您的用例。

    关于java - 如何用下一页填充标题和网格布局 "10 items",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66739843/

    相关文章:

    android - 从ImageTarget Android获取模型对象

    android - Android Fragment中的Retrofit2如何正确实现?

    java - Java 中捕获 U+XXXX(或\uXXXX)字符的正则表达式

    android - 在满足条件之前阻止android Navigation Drawer关闭

    android - ArrayAdapter 中的 ConvertView 为 null

    java - 如何显示网络变化状态的对话?

    android - java.lang.ClassCastException : android. widget.LinearLayout 无法转换为 android.widget.ScrollView

    java - 使用迭代器迭代列表并比较连续元素

    java - 如何向接受 File 参数的函数提供类路径资源?

    java - 将类作为参数传递并返回相同的类对象