在软键盘 Open/Close 之前,RecyclerView 不会更新
RecyclerView doesn't Update until Soft Keyboard is Open/Close
我有一个 Posts Feed(类似于 Facebook News Feed)Activity 在它的布局中我有一个 EditText ,在顶部分享Button,在其下方分享一个RecyclerView。 RecyclerView通过OnCreate
方法中的Adapter从Server获取所有Post并绑定数据,显示所有用户的Post。
当用户 post 通过在 EditText 中输入一些文本并点击共享按钮时,数据被发送到服务器(我正在使用 Retrofit)并且在服务器成功响应后我调用相同的函数调用在 OnCreate
方法中显示所有 Post 以更新 RecyclerView。
我面临的问题是数据已 post 发送到服务器,但仅当我在输入后按 Hide/Close 键盘的后退按钮或 Show/Open 通过点击 EditText 进入键盘。
为了更好的理解,下面是一些代码:
这里我向服务器发送请求时用户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());
}
});
这是 displayFeedPosts 方法:
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:我是Android的新手,如果我做错了事情,我深表歉意。欢迎您提出建议。
注意:关于 ListView here and here 也有人问过同样的问题,但它没有解决我的问题
应该在这里调用 initRecyclerView:
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();
}
我在答案的帮助下解决了上述问题。
实际上 initRecyclerView()
并未在 onResponse()
方法之外执行。将它包含在 onResponse()
方法中并使用 notifyDataSetChanged()
而不是 initRecyclerView()
解决了问题。
数据被填充两次的解决方法我通过如下方式修改displayFeedPosts()
解决了:
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());
}
});
}
我清除了适配器数据,然后用更新的数据再次填充它。
希望我的回答对遇到同样问题的人有所帮助。
PS: 我知道我没有以正确的方式使用我的适配器模型,我只能对所有值使用一个 ArrayList
,我稍后会修改它,现在我专注于主要功能。
我有一个 Posts Feed(类似于 Facebook News Feed)Activity 在它的布局中我有一个 EditText ,在顶部分享Button,在其下方分享一个RecyclerView。 RecyclerView通过OnCreate
方法中的Adapter从Server获取所有Post并绑定数据,显示所有用户的Post。
当用户 post 通过在 EditText 中输入一些文本并点击共享按钮时,数据被发送到服务器(我正在使用 Retrofit)并且在服务器成功响应后我调用相同的函数调用在 OnCreate
方法中显示所有 Post 以更新 RecyclerView。
我面临的问题是数据已 post 发送到服务器,但仅当我在输入后按 Hide/Close 键盘的后退按钮或 Show/Open 通过点击 EditText 进入键盘。
为了更好的理解,下面是一些代码:
这里我向服务器发送请求时用户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());
}
});
这是 displayFeedPosts 方法:
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:我是Android的新手,如果我做错了事情,我深表歉意。欢迎您提出建议。
注意:关于 ListView here and here 也有人问过同样的问题,但它没有解决我的问题
应该在这里调用 initRecyclerView:
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();
}
我在
实际上 initRecyclerView()
并未在 onResponse()
方法之外执行。将它包含在 onResponse()
方法中并使用 notifyDataSetChanged()
而不是 initRecyclerView()
解决了问题。
数据被填充两次的解决方法我通过如下方式修改displayFeedPosts()
解决了:
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());
}
});
}
我清除了适配器数据,然后用更新的数据再次填充它。 希望我的回答对遇到同样问题的人有所帮助。
PS: 我知道我没有以正确的方式使用我的适配器模型,我只能对所有值使用一个 ArrayList
,我稍后会修改它,现在我专注于主要功能。