简体   繁体   中英

RecyclerView doesn't Update until Soft Keyboard is Open/Close

I have a Posts Feed (Something like Facebook News Feed) Activity and in it's layout I have an EditText , share Button at the top and a RecyclerView below it. The RecyclerView shows the Posts of all users by getting all the Posts from Server and binding data through Adapter in OnCreate Method.

When a User post something by typing some text in EditText and hit share Button, the data is sent to Server (I am using Retrofit) and upon Successful Response from Server I call the same function which call in OnCreate Method to show all Posts to update the RecyclerView.

The Problem I am facing is that the data is posted to Server, but the Layout only gets updated only when I press the back button to Hide/Close the Keyboard after typing or Show/Open the Keyboard by tapping the EditText.

Following is Some of the Code for better understanding:

Here I Send Request to Server when User Post something:

Call<CreatePost> call = mAPIService.sharePost(apiKey, post_description);
        call.enqueue(new Callback<CreatePost>() {
            @Override
            public void onResponse(@NonNull Call<CreatePost> call, @NonNull Response<CreatePost> response) {
                boolean error = response.body().getError();
                if (!error) {
                    displayFeedPosts();
                }
            }

            @Override
            public void onFailure(@NonNull Call<CreatePost> call, @NonNull Throwable t) {
                Log.d(TAG, "Error: " + t.getMessage());
            }
        });

Here Is displayFeedPosts Method:

private void displayFeedPosts() {
        Call<FeedPosts> call = mAPIService.displayFeedPosts(apiKey);
        call.enqueue(new Callback<FeedPosts>() {
            @Override
            public void onResponse(@NonNull Call<FeedPosts> call, @NonNull Response<FeedPosts> response) {
                boolean error = response.body().getError();
                if (!error) {
                    ArrayList<Post> feedPosts = response.body().getPosts();
                    for (Post post : feedPosts) {
                        mTripFeedPostUserNames.add(post.getFirstName() + " " + post.getLastName());
                        mTripFeedPostTime.add(post.getPostDatetime());
                        mTripFeedPostContent.add(post.getPostDescription());
                    }
                }
            }

            @Override
            public void onFailure(@NonNull Call<FeedPosts> call, @NonNull Throwable t) {
                Log.d(TAG, "Error: " + t.getMessage());
            }
        });

        initRecyclerView();
    }

    private void initRecyclerView() {
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true);
        RecyclerView recyclerView = findViewById(R.id.trip_feed_recycler_view);
        recyclerView.setNestedScrollingEnabled(false);
        recyclerView.setLayoutManager(layoutManager);
        mTripFeedPostRecyclerViewAdapter = new TripFeedPostRecyclerViewAdapter(this, mTripFeedPostProfileImages, mTripFeedPostUserNames, mTripFeedPostTime, mTripFeedPostContent, mTripFeedPostImages, mTripFeedPostID);
        recyclerView.setAdapter(mTripFeedPostRecyclerViewAdapter);
    }

PS: I am new to Android, I apologise if I have done things the wrong way. Your suggestions are Welcomed.

Note: The same Question has been asked regarding ListView here and here but it doesn't solved my problem

I solved the above problem with the help of Arsalan Khan Answer.

Actually the initRecyclerView() was not executing outside the onResponse() method. Including it inside the onResponse() method and using notifyDataSetChanged() instead of initRecyclerView() solved the problem.

The solution to data being populated twice I solved it by modifying the displayFeedPosts() in the following way:

private void updateFeedPosts() {
        Call<FeedPosts> call = mAPIService.displayFeedPosts(apiKey);
        call.enqueue(new Callback<FeedPosts>() {
            @Override
            public void onResponse(@NonNull Call<FeedPosts> call, @NonNull Response<FeedPosts> response) {
                boolean error = response.body().getError();
                if (!error) {
                    mTripFeedPostProfileImages.clear();
                    mTripFeedPostUserNames.clear();
                    mTripFeedPostTime.clear();
                    mTripFeedPostContent.clear();
                    mTripFeedPostImages.clear();
                    mTripFeedPostID.clear();
                    mTripFeedPostRecyclerViewAdapter.notifyDataSetChanged();
                    ArrayList<Post> feedPosts = response.body().getPosts();
                    for (Post post : feedPosts) {
                        mTripFeedPostProfileImages.add(post.getProfilePicture());
                        mTripFeedPostUserNames.add(post.getFirstName() + " " + post.getLastName());
                        mTripFeedPostTime.add(post.getPostDatetime());
                        mTripFeedPostContent.add(post.getPostDescription());
                        mTripFeedPostImages.add(post.getPostImagePath());
                        mTripFeedPostID.add(post.getPostTripfeedId());
                    }
                    mTripFeedPostRecyclerViewAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onFailure(@NonNull Call<FeedPosts> call, @NonNull Throwable t) {
                Log.d(TAG, "Error: " + t.getMessage());
            }
        });
    }

I cleared the Adapter Data before populating it again with updated data. I hope my answer will help someone having the same problem.

PS: I know I am not using my Adapter Model in correct way, I can use only one ArrayList for all the values, I'll modify it later right now I am focusing on the main functions.

should call initRecyclerView here:

private void displayFeedPosts() {
        Call<FeedPosts> call = mAPIService.displayFeedPosts(apiKey);
        call.enqueue(new Callback<FeedPosts>() {
            @Override
            public void onResponse(@NonNull Call<FeedPosts> call, @NonNull Response<FeedPosts> response) {
                boolean error = response.body().getError();
                if (!error) {
                    ArrayList<Post> feedPosts = response.body().getPosts();
                    for (Post post : feedPosts) {
                        mTripFeedPostUserNames.add(post.getFirstName() + " " + post.getLastName());
                        mTripFeedPostTime.add(post.getPostDatetime());
                        mTripFeedPostContent.add(post.getPostDescription());
                    }
               initRecyclerView();
                }
            }

            @Override
            public void onFailure(@NonNull Call<FeedPosts> call, @NonNull Throwable t) {
                Log.d(TAG, "Error: " + t.getMessage());
            }
        });
    }

private void initRecyclerView() {
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true);
        RecyclerView recyclerView = findViewById(R.id.trip_feed_recycler_view);
        recyclerView.setNestedScrollingEnabled(false);
        recyclerView.setLayoutManager(layoutManager);
        mTripFeedPostRecyclerViewAdapter = new TripFeedPostRecyclerViewAdapter(this, mTripFeedPostProfileImages, mTripFeedPostUserNames, mTripFeedPostTime, mTripFeedPostContent, mTripFeedPostImages, mTripFeedPostID);
        recyclerView.setAdapter(mTripFeedPostRecyclerViewAdapter);
        mTripFeedPostRecyclerViewAdapter.notifyDataSetChanged();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM