在RecyclerView中,当点击返回按钮时如何获取相同的项目位置

7
我已经实现了一个应用程序,在其中在片段中使用了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);
    }
   }
  }

请发布适配器代码。 - Jaymin
请检查更新后的代码。 - Paramjeet Singh
请参见此处:https://dev59.com/ol4c5IYBdhLWcg3wLXka#65645664 - DragonFire
7个回答

4

保存实例代码:

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时你清除了所有数据,当片段再次可见时,你会从第一页向服务器请求。请注释以下代码。
    @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()方法会与setUserVisibilityHint()方法一起被调用。onPause方法将requestcount值设置为1,因此您只能加载第一页的数据。假设您点击了第5页上的项目,那么回到片段时,您只有第一页的数据。当它只有第一页的数据时,您如何假定RecyclerView应该滚动到第5页? - Arvind
是的,因为如果您移动到当前片段的相邻选项卡,则当前片段位于内存中,如果您移动到上一个片段,则不会再次加载当前片段。并且在您移动到的片段中,您已经移动到了最后一页。 - Arvind
创建一个标志值来跟踪 pageCount。如果已经达到页面的最大数量,则不要在 setUserVisiblityHint 方法中调用 getData 方法。 - Arvind
当你到达最后一页时,使用布尔值isLastPageLoaded = false;将其设置为true。在@Override中,public void setUserVisibleHint(boolean isVisibleToUser) {super.setUserVisibleHint(isVisibleToUser);isVisible = isVisibleToUser;if (isStarted && isVisible && (! isLastPageLoaded)) {getData();}} - Arvind
当 JSON 为空时,您正在设置文本 tvMSG.setText("没有更广泛的匹配项"); 添加一些日志,您将得到答案。 - Arvind
显示剩余3条评论

0

在Adapter中将适配器的位置保存到某个变量中。在返回键按下时,使用该位置更改滚动。

linearLayoutManager.scrollToPositionWithOffset(int, int);

活动内部。


0

你需要重写onBackPressed()方法并添加recyclerView.scrollToPosition(position);

@Override
public void onBackPressed() {
    super.onBackPressed();
    recyclerView.scrollToPosition(position);
    finish();
}

我应该在哪里使用这个方法? - Paramjeet Singh
在您的“查看个人资料”活动中,您可以将当前位置作为捆绑包传递给此活动。 - Karmelina Michael
你也可以在 Broader_Match_Tab 的 onResume() 方法中加入 recyclerView.scrollToPosition(position); 并将 position 设为静态。 - Karmelina Michael
这个不会起作用,请查看@Arvind的答案,他说要注释掉onPause代码。 - Paramjeet Singh

0

在 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);


        }

在数据填充后,最好在 adapter.notifyDataSetChanged() 之后使用 ((LinearLayoutManager) mRecylerView.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition) 或者 mRecylerView.smoothScrollToPosition(lastFirstVisiblePosition);


使用 int lastFirstVisiblePosition=-1; 来开始它是顶部的第一个视图(recyclerview项目)。 - tanni tanna
请查看更新的答案,重要的是在数据填充后使用以下行:mRecylerView.smoothScrollToPosition(mPosition); - tanni tanna

0

我之前也遇到了同样的问题,后来我用了一个更简单的解决方案。我只是在onViewCreated()中调用了adapter.startListening();而不是onStart,并在onDestroyView()中调用了adapter.stopListening();而不是onStop()。 这样就防止了整个列表在从下一个活动返回时重新生成,从而保留了先前的滚动位置。


0
我已经按照以下方式解决了问题:
在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();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接