【问题标题】:Getting same item position in RecyclerView, when click on back button单击后退按钮时,在 RecyclerView 中获得相同的项目位置
【发布时间】:2023-04-11 05:48:01
【问题描述】:

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

【问题讨论】:

标签: android android-recyclerview fragment


【解决方案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();
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-09-29
          • 1970-01-01
          • 2012-08-22
          • 2010-11-01
          • 1970-01-01
          • 2013-12-30
          • 2023-04-10
          相关资源
          最近更新 更多