单击后退按钮时,在 RecyclerView 中获得相同的项目位置
Posted
技术标签:
【中文标题】单击后退按钮时,在 RecyclerView 中获得相同的项目位置【英文标题】:Getting same item position in RecyclerView, when click on back button 【发布时间】:2018-07-03 06:54:55 【问题描述】:我已经实现了一个应用程序,我在fragments
中使用RecyclerView
。每个项目上有 3 个按钮、1 个图像和一些文本。如果我滚动并单击“查看配置文件”按钮,则将打开正在成功运行的新活动,但是当我回调按钮时,该项目将出现在开始位置。我需要项目将出现在相同的位置。
物品图片
片段代码
public class Broader_Match_Tab extends Fragment
int lastVisibleItemPosition;
SessionManager session;
private List<SuperHero> listSuperHeroes;
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
public ProgressBar progressBar;
private RequestQueue requestQueue;
private int requestCount1 = 1;
private Boolean isStarted = false;
private Boolean isVisible = false;
boolean isLastPageLoaded = false;
public String email;
TextView tvMSG;
public Broader_Match_Tab()
@Override
public void onStart()
super.onStart();
isStarted = true;
if (isVisible && isStarted)
getData();
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
super.setUserVisibleHint(isVisibleToUser);
isVisible = isVisibleToUser;
if (isStarted && isVisible && (! isLastPageLoaded)) getData();
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View view= inflater.inflate(R.layout.activity_main_test, container, false);
session = new SessionManager(getActivity());
// get user data from session
HashMap<String, String> user = session.getUserDetails();
email = user.get(SessionManager.KEY_EMAIL);
return view;
public void onViewCreated(View v, Bundle savedInstanceState)
super.onViewCreated(v, savedInstanceState);
recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
listSuperHeroes = new ArrayList<>();
requestQueue = Volley.newRequestQueue(getContext());
adapter = new CardAdapter(listSuperHeroes, getActivity());
recyclerView.setAdapter(adapter);
progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
tvMSG = (TextView)v.findViewById(R.id.tvMSG);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int
newState)
super.onScrollStateChanged(recyclerView, newState);
if (isLastItemDisplaying(recyclerView))
getData();
);
private JsonArrayRequest getDataFromServer(int requestCount)
final String DATA_URL = "https://www.example.com";
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(DATA_URL + String.valueOf(requestCount),
new Response.Listener<JSONArray>()
@Override
public void onResponse(JSONArray response)
if (response.length() == 0)
progressBar.setVisibility(View.GONE);
tvMSG.setText("There is no broader matches");
isLastPageLoaded = true;
else
parseData(response);
tvMSG.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
progressBar.setVisibility(View.GONE);
Toast.makeText(getActivity(), "No More Items Available", Toast.LENGTH_SHORT).show();
);
return jsonArrayRequest;
private void getData()
if(!isLastPageLoaded)
requestQueue.add(getDataFromServer(requestCount1));
requestCount1++;
private void parseData(JSONArray array)
for (int i = 0; i < array.length(); i++)
SuperHero superHero = new SuperHero();
JSONObject json = null;
try
json = array.getJSONObject(i);
superHero.setImageUrl(json.getString(Config_Test.TAG_IMAGE_URL));
superHero.setMglId(json.getString(Config_Test.TAG_MGLID));
superHero.setAge(json.getString(Config_Test.TAG_AGE));
superHero.setAgeHeight(json.getString(Config_Test.TAG_AGEHEIGHT));
superHero.setCommunity(json.getString(Config_Test.TAG_COMMUNITY));
superHero.setCaste(json.getString(Config_Test.TAG_CASTE));
superHero.setOccupation(json.getString(Config_Test.TAG_OCCUPATION));
superHero.setIncome(json.getString(Config_Test.TAG_INCOME));
superHero.setShortlist(json.getString(Config_Test.TAG_SHORTLIST));
superHero.setExpress_Intrest(json.getString(Config_Test.TAG_EXPRESSINTREST));
catch (JSONException e)
e.printStackTrace();
listSuperHeroes.add(superHero);
adapter.notifyDataSetChanged();
private boolean isLastItemDisplaying(RecyclerView recyclerView)
if (recyclerView.getAdapter().getItemCount() != 0)
lastVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPosition();
if (lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1)
return true;
return false;
适配器代码
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder>
private static final String url ="https://www.example.com";
private static final String url1 = "https://www.example.com";
private static final String KEY_MATRI_ID_TO="matriID_to";
private static final String KEY_MATRI_ID_BY="matriID_by";
SessionManager session;
public String matri_id_to, matri_id_by, str_gender;
String str_shortlist,str_EI;
//Imageloader to load image
private ImageLoader imageLoader;
private Context context;
//List to store all superheroes
List<SuperHero> superHeroes;
//Constructor of this class
public CardAdapter(List<SuperHero> superHeroes, Context context)
super();
//Getting all superheroes
this.superHeroes = superHeroes;
this.context = context;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.superheroes_list, parent, false);
// Session class instance
session = new SessionManager(context);
session.checkLogin();
// get user data from session
HashMap<String, String> user = session.getUserDetails();
matri_id_by = user.get(SessionManager.KEY_EMAIL);
str_gender = user.get(SessionManager.KEY_GENDER);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
@Override
public void onBindViewHolder(final ViewHolder holder, final int position)
//Getting the particular item from the list
final SuperHero superHero = superHeroes.get(position);
//Loading image from url
imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
if(str_gender.equalsIgnoreCase("Male"))
imageLoader.get(superHero.getImageUrl(), ImageLoader.getImageListener(holder.imageView, R.drawable.image, R.drawable.girl));
else
imageLoader.get(superHero.getImageUrl(), ImageLoader.getImageListener(holder.imageView, R.drawable.image, R.drawable.boy));
int pos = getItemViewType(position);
if(superHeroes.get(pos).getImageUrl() == null)
holder.imageView.setVisibility(View.GONE);
else
holder.imageView.setImageUrl(superHero.getImageUrl(), imageLoader);
holder.textViewId.setText(superHero.getMglId());
holder.AgeHeight.setText(superHero.getAgeHeight()+" / "+superHero.getAge());
holder.Community.setText(superHero.getCommunity()+" / "+superHero.getCaste());
holder.Occupation.setText(superHero.getOccupation());
holder.Income.setText(superHero.getIncome());
str_shortlist = superHero.getShortlist();
if(str_shortlist.toString().equalsIgnoreCase("Shortlisted"))
holder.btnShortlist.setText(str_shortlist);
holder.btnShortlist.setBackgroundColor(Color.parseColor("#FF0E3671"));
holder.btnShortlist.setEnabled(false);
else
holder.btnShortlist.setEnabled(true);
holder.btnShortlist.setText(str_shortlist);
holder.btnShortlist.setBackgroundColor(Color.parseColor("#2a7fff"));
str_EI = superHero.getExpress_Intrest();
Log.e("str_EI_____",str_EI);
if(str_EI.toString().equalsIgnoreCase("Accepted"))
holder.btnEI.setText(str_EI);
holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
holder.btnEI.setEnabled(false);
else if(str_EI.toString().equalsIgnoreCase("Reject"))
holder.btnEI.setText(str_EI);
holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
holder.btnEI.setEnabled(false);
else if(str_EI.toString().equalsIgnoreCase("Declined"))
holder.btnEI.setText(str_EI);
holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
holder.btnEI.setEnabled(false);
else if(str_EI.toString().equalsIgnoreCase("Pending.."))
holder.btnEI.setText(str_EI);
holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
holder.btnEI.setEnabled(false);
else
holder.btnEI.setEnabled(true);
holder.btnEI.setText(str_EI);
holder.btnEI.setBackgroundColor(Color.parseColor("#00aa88"));
holder.btnShortlist.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
superHero.setShortlist("Wait...");
holder.btnShortlist.setText(superHero.getShortlist());
matri_id_to = superHero.getMglId();
holder.shortlist(position);
);
holder.btnViewProfile.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Intent n = new Intent(holder.itemView.getContext(),BlankActivity.class);
String str_id = holder.textViewId.getText().toString();
n.putExtra("ID",str_id);
holder.itemView.getContext().startActivity(n);
);
holder.btnEI.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
superHero.setExpress_Intrest("Wait...");
holder.btnEI.setText(superHero.getExpress_Intrest());
matri_id_to = superHero.getMglId();
holder.expressInterest(position);
);
public SuperHero getItem(int position)
return superHeroes.get(position);
@Override
public int getItemCount() return superHeroes.size();
@Override
public int getItemViewType(int position)
return position;
class ViewHolder extends RecyclerView.ViewHolder
public NetworkImageView imageView;
public TextView textViewId;
public TextView AgeHeight;
public TextView Community;
public TextView Occupation;
public TextView Income;
public Button btnShortlist;
public Button btnViewProfile;
public Button btnEI;
//Initializing Views
public ViewHolder(final View itemView)
super(itemView);
imageView = (NetworkImageView) itemView.findViewById(R.id.imageViewHero);
textViewId = (TextView) itemView.findViewById(R.id.textViewId);
AgeHeight = (TextView) itemView.findViewById(R.id.AgeHeight);
Community = (TextView) itemView.findViewById(R.id.Community);
Occupation = (TextView) itemView.findViewById(R.id.Occupation);
Income = (TextView) itemView.findViewById(R.id.Income);
btnShortlist = (Button) itemView.findViewById(R.id.btnshort);
btnViewProfile = (Button) itemView.findViewById(R.id.buttonViewProfile);
btnEI = (Button) itemView.findViewById(R.id.btnExpressIntrest);
public void shortlist(final int position)
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>()
@Override
public void onResponse(String response)
if (response.trim().equalsIgnoreCase("success"))
superHeroes.get(position).setShortlist("Shortlisted");
// holder.btnShortlist.setText(superHero.getShortlist());
notifyDataSetChanged();
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
Toast.makeText(context, error.toString(), Toast.LENGTH_LONG).show();
)
@Override
protected Map<String, String> getParams()
Map<String, String> params = new HashMap<String, String>();
params.put(KEY_MATRI_ID_BY, matri_id_by);
params.put(KEY_MATRI_ID_TO, matri_id_to);
return params;
;
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.add(stringRequest);
public void expressInterest(final int position)
StringRequest stringRequest1 = new StringRequest(Request.Method.POST, url1, new Response.Listener<String>()
@Override
public void onResponse(String response)
if(response.trim().equalsIgnoreCase("success"))
superHeroes.get(position).setExpress_Intrest("Pending..");
notifyDataSetChanged();
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
Toast.makeText(context, error.toString(), Toast.LENGTH_LONG).show();
)
@Override
protected Map<String, String> getParams()
Map<String, String> params = new HashMap<String, String>();
params.put(KEY_MATRI_ID_BY,matri_id_by);
params.put(KEY_MATRI_ID_TO,matri_id_to);
return params;
;
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.add(stringRequest1);
【问题讨论】:
请发布适配器代码 请检查更新后的代码 看这里:***.com/a/65645664/3904109 【参考方案1】:保存实例代码:
Parcelable mListState;
protected void onSaveInstanceState(Bundle state)
super.onSaveInstanceState(state);
// Save list state
mListState = mLayoutManager.onSaveInstanceState();
state.putParcelable(LIST_STATE_KEY, mListState);
恢复状态码:
protected void onRestoreInstanceState(Bundle state)
super.onRestoreInstanceState(state);
// Retrieve list state and list/item positions
if(state != null)
mListState = state.getParcelable(LIST_STATE_KEY);
在 onResume() 中更新布局管理器:
@Override
protected void onResume()
super.onResume();
if (mListState != null)
mLayoutManager.onRestoreInstanceState(mListState);
希望对你有帮助
【讨论】:
【参考方案2】:主要问题是 onPause 您正在清除整个数据,当片段再次可见时,您正在从页面 1 请求服务器。注释以下代码。
@Override
public void onPause()
super.onPause();
//listSuperHeroes.clear();
//adapter.notifyDataSetChanged();
//requestCount1=1;
在此处更新 isLastPageLoaded:
private boolean isLastPageUpdated = false;
private JsonArrayRequest getDataFromServer(int requestCount)
final String DATA_URL = "https://www.XYZ.php?matri_id="+email+"&page=";
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(DATA_URL + String.valueOf(requestCount),
new Response.Listener<JSONArray>()
@Override
public void onResponse(JSONArray response)
if (response.length() == 0)
progressBar.setVisibility(View.GONE);
tvMSG.setText("There is no broader matches");
isLastPageLoaded = true;
else
parseData(response);
tvMSG.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
progressBar.setVisibility(View.GONE);
Toast.makeText(getActivity(), "No More Items
Available", Toast.LENGTH_SHORT).show();
);
return jsonArrayRequest;
在getData()中
private void getData()
if(!isLastPageUpdated)
requestQueue.add(getDataFromServer(requestCount1));
requestCount1++;
【讨论】:
所以当你启动新的活动时,片段的 onPause 方法被调用并且所有适配器数据都被清除。当您从当前活动按下返回按钮时,onresume() 方法与 setUserVisiblityHint() 方法一起被调用。 onPause 方法将 requestcount 值设置为 1,因此您只能为第一页加载数据。假设您单击了第 5 页上的项目,所以回到片段您只有第一页数据。您如何假设只有第一页数据的回收站视图应该滚动到第 5 页?? 当我滚动所有项目并更改选项卡并返回上一个选项卡时,它会显示“没有更多可用项目” 是的,因为如果您移动到当前片段的相邻选项卡,则当前片段在内存中,如果您移动到前一个片段,则不会再次加载它。在片段中,您已移至最后一页。 创建一个标志值来跟踪 pageCount。如果您已经达到了页面的最大数量,则不要在 setUserVisiblityHint 方法中调用 getData 方法。 取一个布尔值 isLastPageLoaded = false;当你到达最后一页时 make isLastPageLoaded = true;在@Override public void setUserVisibleHint(boolean isVisibleToUser) super.setUserVisibleHint(isVisibleToUser); isVisible = isVisibleToUser; if (isStarted && isVisible && (!isLastPageLoaded)) getData(); 【参考方案3】:将适配器的位置保存在适配器的某个变量中。使用
将滚动更改到后按时的该位置linearLayoutManager.scrollToPositionWithOffset(int, int);
内部活动。
【讨论】:
【参考方案4】:你需要重写 onBackPressed() 并添加 recyclerView.scrollToPosition(position);
@Override
public void onBackPressed()
super.onBackPressed();
recyclerView.scrollToPosition(position);
finish();
【讨论】:
我应该在哪里使用这个方法 在您的视图配置文件活动中。您可以将当前位置传递给该活动的捆绑包 您也可以将recyclerView.scrollToPosition(position);
放入您的Broader_Match_Tab onResume() 并将位置设为静态
这行不通,请检查@Arvind 的答案,他在哪里评论 onPause 代码。【参考方案5】:
保存在 onSaveInstanceState 中点击的项目的位置并将其传递给 scrollToPosition 或
下面试试
private static final String SELECTED_KEY = "selected_position";
@Override
public void onSaveInstanceState(Bundle outState)
lastFirstVisiblePosition = ((LinearLayoutManager)mRecylerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
outState.putInt(SELECTED_KEY, lastFirstVisiblePosition);
在 Oncreate 中
已编辑..
if(savedInstanceState != null && savedInstanceState.containsKey(SELECTED_KEY))
lastFirstVisiblePosition = savedInstanceState.getInt(SELECTED_KEY);
使用 ((LinearLayoutManager) mRecylerView.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition) 或
mRecylerView.smoothScrollToPosition(lastFirstVisiblePosition); 填充数据后,最好在 adapter.notifyDataSetChanged();
【讨论】:
使用 int lastFirstVisiblePosition=-1;首先是顶部的第一个视图(recyclerview 项)。 请查看更新后的答案,重要的是在填充数据后使用下面的行,mRecylerView.smoothScrollToPosition(mPosition);【参考方案6】:我之前遇到过同样的问题,然后我用一个更简单的解决方案解决了我的问题。我只是在onViewCreated()
中调用了适配器.startListening();
而不是onStart
并在onDestroyView()
中调用了适配器.stopListening();
而不是onStop()
。
这会阻止整个列表在从下一个活动返回时重新生成,从而保留之前的滚动位置。
【讨论】:
【参考方案7】:我已经解决了如下问题:
在 onViewCreated 和 onStart 中都调用了 .startListening
在 onDestroyView 中调用 .stopListening
不要在 onStop 中调用 .stopListening
我在片段中的代码如下:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle
savedInstanceState)
super.onViewCreated(view, savedInstanceState);
if (mAdapterHb != null)
mAdapterHb.startListening();
@Override
public void onStart()
super.onStart();
if (mAdapterHb != null)
mAdapterHb.startListening();
@Override
public void onStop()
super.onStop();
// if (mAdapterHb != null)
// mAdapterHb.stopListening();
//
@Override
public void onDestroyView()
super.onDestroyView();
if (mAdapterHb != null)
mAdapterHb.stopListening();
【讨论】:
以上是关于单击后退按钮时,在 RecyclerView 中获得相同的项目位置的主要内容,如果未能解决你的问题,请参考以下文章
当我单击浏览器后退按钮或移动设备后退按钮时,保留选定的选项卡
为啥在我第一次单击按钮时在我的 RecyclerView 中调用绑定?