如何使用LazyLoading在单个回收视图或适配器中显示多个数据源数据?

时间:2018-12-13 04:47:59

标签: java android android-fragments android-recyclerview adapter

上面的图像是我要开发的简单设计。 我有四种类型的数据,它们具有不同的视图类型,如下面的图像在此处输入图像描述。但这不是问题。问题是数据将来自具有延迟加载的不同API,例如,当用户从回收视图滚动列表时,它将从服务器获取数据。我的问题是如何将它们合并到单个适配器中,因为我需要使用延迟加载。因此我无法一次加载整个数据,因此我需要调用不同类型的API,例如目标列表API,评估API,发布API等。当用户滚动时。任何人都可以给我一个例子的想法。我该如何处理?此外,当用户滚动时,它将调用另一个api,例如count和comment count。目前,我正在调用单个API,并在单个回收视图中进行显示。目前,我正在使用android体系结构组件LiveData

片段:

public class NewsFeedFragment extends FcaFragment {

    private View view;
    private RecyclerView postRecyclerView;
    private PostsAdapter postsAdapter;
    private List<Post> posts;
    private TimelineViewModel timelineViewModel;
    private ImageView addPostView;
    private View addPostPanel;
    private long lastApiCallTime;
    private SwipyRefreshLayout swipeRefresh;
    private long lastScroolItemInPost= 0;

    public NewsFeedFragment() {

    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if(lastScroolItemInPost  < 1) {
            initViewModel(1 , 0 , true);
            lastScroolItemInPost = 1;
        }else {
            initViewModel(((int) lastScroolItemInPost + 5), lastScroolItemInPost , true);
            lastScroolItemInPost += 5;
        }


        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ownerActivity);

        view = inflater.inflate(R.layout.fragment_news_feed, container, false);
        postRecyclerView = (RecyclerView) view.findViewById(R.id.postRecyclerView);
        postRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView postRecyclerView, int dx, int dy) {
                super.onScrolled(postRecyclerView, dx, dy);


                int lastVisiableItemInPostList   = linearLayoutManager.findLastVisibleItemPosition();


                if(lastScroolItemInPost < lastVisiableItemInPostList)
                {
                        if(lastScroolItemInPost == 1)
                        {
                        initViewModel((int) (lastScroolItemInPost + 2), ( lastScroolItemInPost - 2 )  , false);
                        lastScroolItemInPost += 2;
                        }else{
                            initViewModel((int) (lastScroolItemInPost + 2), ( lastScroolItemInPost - 2 ) , false );
                            lastScroolItemInPost += 2;
                        }


                }

               }

        });

        posts = new ArrayList<>();

        postRecyclerView.setLayoutManager(linearLayoutManager);
        postsAdapter = new PostsAdapter(ownerActivity,posts,timelineViewModel);
        postRecyclerView.setAdapter(postsAdapter);
        swipeRefresh = (SwipyRefreshLayout) view.findViewById(R.id.swipeRefresh);
        swipeRefresh.setOnRefreshListener(new SwipyRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh(SwipyRefreshLayoutDirection direction) {
                if(direction == SwipyRefreshLayoutDirection.TOP){
                    timelineViewModel.fetchPosts2();
                }

                if(direction == SwipyRefreshLayoutDirection.BOTTOM){
                    timelineViewModel.fetchPosts();
                }
            }
        });




        return view;
    }




    private void initViewModel(int lastVisiableItemInPostList , long lastScroolItemInPost , boolean isFirstTimeOpenFeedFragment) {
        TimelineViewModel.Factory factory = new TimelineViewModel.Factory(UserPreferences.getToken(ownerActivity), TaskUtils.getMySelfContact(ownerActivity));
        timelineViewModel = ViewModelProviders.of(this,factory).get(TimelineViewModel.class);
        timelineViewModel.getPostList().observe(this, new Observer<List<Post>>() {
            @Override
            public void onChanged(@Nullable List<Post> posts) {

                postsAdapter.setPostList(posts);
                swipeRefresh.setRefreshing(false);

            }
        });
        timelineViewModel.getPostDeleted().observe(this, new Observer<Boolean>() {
            @Override
            public void onChanged(@Nullable Boolean aBoolean) {
                if(aBoolean){
                    postsAdapter.setPostList(Post.getAll());
                }
            }
        });
        timelineViewModel.init( lastVisiableItemInPostList ,  lastScroolItemInPost ,isFirstTimeOpenFeedFragment);
    }

}

ViewModel:

public class TimelineViewModel extends FCViewModel implements PostDetailsDownloadManager.PostDetailDownloadedListener,OnContactReceivedListner{





    public TimelineViewModel(String token,Contact user){
        super(token);
        this.user = user;

        post = new MutableLiveData<>();
        postDeleted = new MutableLiveData<>();
    }

    public void init(int lastVisiableItemInPostList , long lastScroolItemInPost , boolean isFirstTimeOpenFeedFragment){
        repository = 
        //postDetailsDownloadManager = ServiceLocator.getServiceLocator().postDetailsDownloadManager;

        likePostDownloadManager = ServiceLocator.getServiceLocator().likePostDownloadManager;
        likePostDownloadManager.setPostDetailDownloadedListener(new DataDownloadManager.DataDownloadedListener<LikePostTouple>() {
            @Override
            public void onDataDownloaded(List<LikePostTouple> dataTouple) {
                TimelineViewModel.this.post.setValue(Post.getAll());
            }

            @Override
            public void onSingleDataDownloaded(LikePostTouple dataTouple) {

            }
        });

        postDetailDownloadManager = ServiceLocator.getServiceLocator().postDetailDownloadManager;
        postDetailDownloadManager.setPostDetailDownloadedListener(new DataDownloadManager.DataDownloadedListener<PostTouple>() {
            @Override
            public void onDataDownloaded(List<PostTouple> dataTouple) {
                TimelineViewModel.this.post.setValue(Post.getAll());
            }

            @Override
            public void onSingleDataDownloaded(PostTouple dataTouple) {

            }
        });
        post.setValue(Post.getAll());
        if(isFirstTimeOpenFeedFragment)
        {
            fetchPosts2();
        }

        try {
            if(Post.getAll().size() > 0)
            {
                List<Post> tempPosts = Post.getAll();
                List<Post> passList = tempPosts.subList( (int) lastScroolItemInPost ,lastVisiableItemInPostList);
                fetchLikesOfPosts(passList);
            }else{
                fetchLikesOfPosts(Post.getAll());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        Log.d("Testing Injecting", repository.toString());
    }

    public LiveData<List<Post>> getPostList() {
        return post;
    }

    public MutableLiveData<Boolean> getPostDeleted() {
        return postDeleted;
    }

    boolean isContactFetched = false;

    public void fetchPosts(){
        if(Contact.getAll().size() < 1){
            fetchContacts();
            return;
        }
        Map<String,Object> requestData = new HashMap<>();
        requestData.put("type",1);
        requestData.put("cpid",Post.getLastPid());
        isDataLoading = true;
        repository.getData(new Repository.DataFetchedListener<List<Post>>() {
            @Override
            public void onDataFetched(List<Post> posts) {
                isDataLoading = false;
                Log.d("fetched posts",""+posts.size());
                post.setValue(Post.getAll());
                fetchPostDetails(posts);
                if(posts.size() > 0){
                    fetchLikesOfPosts(posts);
                }
            }
        },requestData);
    }


    private boolean isDataLoading = false;
    public void fetchPosts2(){
        if(Contact.getAll().size() < 1){
            fetchContacts();
            return;
        }
        Map<String,Object> requestData = new HashMap<>();
        requestData.put("type",2);
        requestData.put("cpid", Post.getFirstPid()); // cpid means cursor pid
        isDataLoading = true;
        repository.getData(new Repository.DataFetchedListener<List<Post>>() {
            @Override
            public void onDataFetched(List<Post> posts) {
                isDataLoading = false;
                Log.d("fetched posts",""+posts.size());
                post.setValue(Post.getAll());
                fetchPostDetails(posts);
                if(posts.size() > 0){
                    fetchLikesOfPosts(posts);
                }
            }
        },requestData);
    }

    public boolean isDataLoading() {
        return isDataLoading;
    }



    private void fetchContacts() {
        contactRepository.getData(new Repository.DataFetchedListener<List<Contact>>() {
            @Override
            public void onDataFetched(List<Contact> data) {
                if(data.size()>0 && !isContactFetched) {
                    fetchPosts2();
                    isContactFetched = true;
                }
            }
        },null);
    }



    @NonNull
    private PostTouple getPostToubleFromPost(Post post) throws JSONException {
        Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
        String json =   gson.toJson(post);
        JSONObject postJson = new JSONObject(json);
        return new PostTouple(postJson,post.getPid());
    }

    @NonNull
    private LikePostTouple getLkePostToupleFromPost(Post post) throws JSONException {
        Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
        String json =   gson.toJson(post);
        JSONObject postJson = new JSONObject(json);
        return new LikePostTouple(postJson,post.getPid());
    }

    public void giveLike(String token, final long pid){
        Map<String,Object> requestData = new HashMap<>();
        requestData.put("token",token);
        requestData.put("pid",Long.toString(pid));

        likeRepository.postData(new Repository.DataFetchedListener<Post>() {
            @Override
            public void onDataFetched(Post data) {
                Log.d("Like post", data.toString());
                Post post = getPostById(pid);
                post.setLikes(data.getLikes());
                post.setComments(data.getComments());
                TimelineViewModel.this.post.setValue(TimelineViewModel.this.post.getValue());
                fetchLikesOfLikedPost(data);
            }
        },requestData);
    }

    private void fetchLikesOfLikedPost(Post data) {
        try {
            likePostDownloadManager.addItemInQueue(getLkePostToupleFromPost(data));
            likePostDownloadManager.startDownload();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private Post getPostById(long pid){
        List<Post> posts = post.getValue();
        for(Post post : posts){
            if(post.getPid()==pid){
                return post;
            }
        }
        return null;
    }

    public Contact getSenderContactFromComment(Post post) {
        if(post.getPqrc().equals(user.getUserId())){
            return user;
        }
        Contact contact = Contact.getByUserId(post.getPqrc());

        return contact;
    }

    public String getDescriptionForType5(Post post,String message){

        try {
            PostDetail postDetail = PostDetail.getByPostId(post.getPid());
            if(postDetail!=null) {
                String qrc = JSonUtils.qrcFromCntOfPostDetails(postDetail.getContent());
                int sid = JSonUtils.skillidFromCntOfPostDetails(postDetail.getContent());
                if (qrc == null || sid == 0) {
                    return "";
                }
                SkillDb skill = SkillDb.getBySId(Integer.toString(sid));

                Contact contact = getPosterContact(post.getPqrc());

                return contact.getName() + " " + message + " " + skill.getSkillName() + ".";
            }

            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public String getDescriptionForPost(Post post, String message){
        if(post.getCtype()==1){
            return post.getDescr();
        }

        if(post.getCtype() == 2){
            String postDetail = getContent(post);
            if (postDetail != null) return Html.fromHtml("<a href=\""+ postDetail +"\">"+postDetail+"</a>").toString();
        }

        if(post.getCtype()==5){
            return getDescriptionForType5(post, message);
        }

        return "";

    }

    @Nullable
    public String getContent(Post post) {
        PostDetail postDetail = PostDetail.getByPostId(post.getPid());
        if(postDetail!=null){
            return postDetail.getContent();
        }
        return null;
    }


    public Contact getPosterContact(String qrc){
        try {
            String userqrc = user.getUserId();
            if (userqrc.equals(qrc)) {
                return user;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        try {
            return Contact.getByUserId(qrc);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public void fetchUrlPreview(String url, final UrlMetaDataFetchListener metaDataFetchListener){
        String modifiedUrl = !url.contains("http://")&&!url.contains("https://")? "http://"+url : url;
        TextCrawler textCrawler = new TextCrawler();


        LinkPreviewCallback linkPreviewCallback = new LinkPreviewCallback() {
            @Override
            public void onPre() {

            }

            @Override
            public void onPos(SourceContent sourceContent, boolean b) {
                String imageUrl = sourceContent.getImages().isEmpty()? "" : sourceContent.getImages().get(0);
                metaDataFetchListener.onMetaDataFetched(sourceContent.getTitle(),sourceContent.getDescription(), imageUrl);
            }
        };

        textCrawler.makePreview(linkPreviewCallback, modifiedUrl,1);
    }


    public interface UrlMetaDataFetchListener{
        void onMetaDataFetched(String title, String description, String imageUrl);
    }

    @Override
    public void onPostDownloaded(PostTouple postTouple) {
        this.post.setValue(Post.getAll());
    }

    @Override
    public void onContactsReceived() {
        fetchPosts();
    }


    public void deletePost(long pid) {
        Map<String, Object> requestData = new HashMap<>();
        requestData.put("token",token);
        requestData.put("pid",pid);
        repository.postData(new Repository.DataFetchedListener<Post>() {
            @Override
            public void onDataFetched(Post data) {
                postDeleted.setValue(data!=null);
            }
        },requestData);
    }

    public boolean isMyPost(Post post){
        return user.getUserId().equals(post.getPqrc());
    }

    public static class Factory extends ViewModelProvider.NewInstanceFactory {

         private String token;
         private Contact user;

        public Factory(String token,Contact user) {
            this.token = token;
            this.user = user;
        }

        @Override
        public <T extends ViewModel> T create(Class<T> modelClass) {

            return (T) new TimelineViewModel(token,user);
        }
    }
}

适配器:

公共类PostsAdapter扩展了RecyclerView.Adapter {

private Context context;
private List<Post> postList;
private int[] badges = {R.drawable.badge1, R.drawable.badge2, R.drawable.badge3};
private List<Integer> randomNumbers = Utils.getRandomNumberList(2,true);
private ArrayDeque<Integer> randomQueue = new ArrayDeque<>(randomNumbers);
private static Map<Long,URLPreview> urlPreviewMap = new HashMap<>();
private TimelineViewModel timelineViewModel;

public PostsAdapter(Context context, List<Post> postList, TimelineViewModel timelineViewModel){
    super();
    this.context = context;
    this.postList = postList;
    this.timelineViewModel = timelineViewModel;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.post_item_layout, null);
    PostViewHolder postViewHolder = new PostViewHolder(view);
    postViewHolder.setIsRecyclable(false);
    return postViewHolder;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    final Post post = postList.get(position);
    final PostViewHolder postViewHolder = (PostViewHolder) holder;
    final String postDetail = timelineViewModel.getDescriptionForPost(post,context.getResources().getString(R.string.postType5message));


    setPostDescription(post, postViewHolder, postDetail);
    handlePreviewVisibility(post, postViewHolder);


    postViewHolder.setLikes(""+post.getLikes()+" Likes");
    postViewHolder.setCommentCount("" + post.getComments() + " Comments");
    postViewHolder.setSupDescription("Posted By System");

    int randomNumber = getRandomNumber();
    postViewHolder.setBadgeIcon(badges[randomNumber]);

    setPostLikedIndicator(post, postViewHolder);

    postViewHolder.getLikeButtonWrapper().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {


            giveLikeToPost(post);
            if(post.getIsLiked() == 0) {
                post.setLikes(post.getLikes() + 1);
                postViewHolder.setLikes("" + post.getLikes() + " Likes");
                post.setIsLiked(1);
                setPostLikedIndicator(post, postViewHolder);
            }
        }
    });

    postViewHolder.getCommentPanel().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            CommentPostFragment fragment = CommentPostFragment.GetInstance(post.getPid());
            ViewUtils.launchFragmentKeepingInBackStack(context,fragment);
        }
    });

    Contact contact = timelineViewModel.getPosterContact(post.getPqrc());

    if(contact!=null && TaskUtils.isNotEmpty(contact.getImageToken())){
        Utils.setImageToImageView(postViewHolder.getPosterImage(),timelineViewModel.getToken(),contact.getImageToken());
        postViewHolder.getPosterNameTextView().setText(contact.getName());
    }


    postViewHolder.getPostingDate().setText(Utils.getDateFromMilliseconds(post.getdC()));
    if(post.getCtype() != 3)
    {

        postViewHolder.contentImage.setVisibility(View.GONE);
        postViewHolder.fullScreenIndicatorIcon.setVisibility(View.GONE);
    }

    if(post.getCtype() == 3){
        setContentOfType3(post, postViewHolder);
    }




}

@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
    super.onViewRecycled(holder);
    PostViewHolder viewHolder = (PostViewHolder) holder;
    viewHolder.pTitle.setText("");
    viewHolder.pDescription.setText("");
    viewHolder.pImage.setImageDrawable(null);

}

private void handlePreviewVisibility(Post post, PostViewHolder postViewHolder) {
    if(post.getCtype()==2){
        postViewHolder.preview.setVisibility(View.VISIBLE);
    }else{
        postViewHolder.preview.setVisibility(View.GONE);
    }
}

private void handleShowingOptionsIcon(Post post, PostViewHolder postViewHolder) {
    if(post.getCtype()!=5 && timelineViewModel.isMyPost(post)){
        postViewHolder.options.setVisibility(View.VISIBLE);
    }else{
        postViewHolder.options.setVisibility(View.GONE);
    }
}





private void giveLikeToPost(Post post) {
    post.setLikes(post.getLikes()+1);

    post.setIsLiked(1);

    //notifyDataSetChanged();

    timelineViewModel.giveLike(UserPreferences.getToken(context),post.getPid());

}

private void setPostLikedIndicator(Post post, PostViewHolder postViewHolder) {
    if(post.getIsLiked()==1) {
        postViewHolder.getLikeButton().setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_like_red, null));
    }else{
        postViewHolder.getLikeButton().setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_like_filled, null));
    }
}

private void setPostDescription(final Post post, final PostViewHolder postViewHolder, final String postDetail) {
    if(post.getCtype()==2){

        String postDescription = "<p>"+ post.getDescr()+"</p>";
        postViewHolder.description.setText( Html.fromHtml(postDescription +"<a href=\""+ postDetail +"\">"+postDetail+"</a>")  );
        postViewHolder.descriptionContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String url = !postDetail.contains("http://")&&!postDetail.contains("https://")? "http://"+postDetail : postDetail;
                Uri uri = Uri.parse(url);
                context.startActivity(new Intent(Intent.ACTION_VIEW,uri));
            }
        });
        URLPreview urlPreview = null;
        if((urlPreview=urlPreviewMap.get(post.getPid()))==null) {
            timelineViewModel.fetchUrlPreview(postDetail, new TimelineViewModel.UrlMetaDataFetchListener() {
                @Override
                public void onMetaDataFetched(String title, String description, String imageUrl) {
                    showURLPreview(title, description, imageUrl, postViewHolder);
                    urlPreviewMap.put(post.getPid(),new URLPreview(title,description,imageUrl));
                }
            });
        }else {
            showURLPreview(urlPreview.getTitle(),urlPreview.getDescription(),urlPreview.getImageUrl(),postViewHolder);
        }

    }else if(post.getCtype() == 3)
    {
      String postDescription = post.getDescr();
      postViewHolder.description.setText(postDescription);
    }
    else {
        postViewHolder.setDescription(postDetail);
    }
}
private void initImageClickListener(final ImageView imageView, final String pictureLink) {
    imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            List<String> pictureLinks = new ArrayList<String>();
            pictureLinks.add(pictureLink);


            int[] screenLocation = new int[2];
            imageView.getLocationOnScreen(screenLocation);

            ImagePagerFragment imagePagerFragment = ImagePagerFragment.newInstance(pictureLinks, 0, screenLocation, imageView.getWidth(), imageView.getHeight());
            ViewUtils.launchPopUpFragmentUpdated(context, imagePagerFragment);
        }
    });
}


private void showURLPreview(String title, String description, String imageUrl, PostViewHolder postViewHolder) {

context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if(!TaskUtils.isEmpty(imageUrl)) {
        Picasso.with(context)
                .load(imageUrl)
                .into(postViewHolder.pImage);
    }

view.findViewById(R.id.description);

    postViewHolder.pTitle.setText(title);
    postViewHolder.pDescription.setText(description);


}


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

private int getRandomNumber(){
    if(!randomQueue.isEmpty()){
        return randomQueue.poll();
    }

    randomQueue = new ArrayDeque<>(randomNumbers);
    return randomQueue.poll();
}

public void setPostList(List<Post> postList) {
    this.postList = postList;
    notifyDataSetChanged();
    Log.d("Data rec", postList.size()+"");
}

class PostViewHolder extends RecyclerView.ViewHolder implements PopupMenu.OnMenuItemClickListener {




    }

    public void setLikes(String likes) {
        this.likes.setText(likes);
    }
    public void setCommentCount(String commentCount)
    {
        this.commentCount.setText(commentCount);
    }

    public void setDescription(String description){
        this.description.setText(description);
    }

    public void setSupDescription(String subDescription){
        this.supDescription.setText(subDescription);
    }

    public void setBadgeIcon(int resID){
        Utils.setImageViewFromResource(badgeIcon,resID);
    }

    public ImageView getLikeButton() {
        return likeButton;
    }
    public RelativeLayout getLikeButtonWrapper()
    {
        return likeButtonWrapper;
    }

    public ImageView getCommentButton() {
        return commentButton;
    }

    public ImageView getPosterImage() {
        return posterImage;
    }

    public TextView getPosterNameTextView() {
        return posterNameTextView;
    }

    public TextView getPostingDate() {
        return postingDate;
    }

    public RelativeLayout getCommentPanel() {
        return commentPanel;
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        timelineViewModel.deletePost(postList.get(getAdapterPosition()).getPid());
        return false;
    }
}

}

0 个答案:

没有答案