如何在PopupWindow中展示RecyclerView数据?
问题描述
已通过Volley成功获取数据并在Activity或Spinner中展示,但不清楚如何在PopupWindow内的RecyclerView中展示数据:
- 不知道该在哪里初始化PopupWindow内的RecyclerView和适配器
- 不清楚应在何时调用
GET_MALL_WEB_CALL()方法 - 不知道如何将网络请求得到的数据传入PopupWindow实现展示
- 想了解是否有其他更优的实现方式
现有代码
SetupActivity.java
public class SetupActivity extends AppCompatActivity { private RequestQueue requestQueue2; private RecyclerView mallRecyclerView; private MallAdapter mallRecyclerAdapter; List<ModelMall> newMallModels = new ArrayList<>(); private PopupWindow currentPopupWindow; // 新增:用于控制已显示的Popup @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_setup); initViews(); // 初始化Volley请求队列(原代码遗漏,必须补充) requestQueue2 = Volley.newRequestQueue(this); EditText popupButton = findViewById(R.id.editTextMall); popupButton.setInputType(InputType.TYPE_NULL); popupButton.setOnClickListener(v -> { // 先检查数据是否已加载,未加载则发起请求并显示加载弹窗 if (newMallModels.isEmpty()) { MallAdapter.showSimpleProgressDialog(this, "加载中", "获取商场数据...", false); GET_MALL_WEB_CALL(); } else { showPopup(v); } }); // 可选:Activity启动时预加载数据 // GET_MALL_WEB_CALL(); } private void initViews() { imageVProfileSmall = findViewById(R.id.profileImg); // 原Activity内的RecyclerView初始化(如果不再需要可移除) LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); mallRecyclerView = findViewById(R.id.recyclerView); mallRecyclerView.setLayoutManager(layoutManager); mallRecyclerAdapter = new MallAdapter(this); mallRecyclerView.setAdapter(mallRecyclerAdapter); } private void GET_MALL_WEB_CALL() { String HTTP_SERVER_URL = "http://GETMALLAPI"; JsonArrayRequest jsArrRequest = new JsonArrayRequest( Request.Method.GET, HTTP_SERVER_URL, null, response -> { GET_MALL_PARSE(response); MallAdapter.removeSimpleProgressDialog(); // 数据加载完成后自动弹出Popup EditText popupButton = findViewById(R.id.editTextMall); showPopup(popupButton); }, error -> { Log.i("ERROR", "Event Web call Error"); error.printStackTrace(); MallAdapter.removeSimpleProgressDialog(); }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> params = new HashMap<>(); params.put("Content-Type", "application/x-www-form-urlencoded"); params.put("Authorization", "Bearer " + getFromSP("token")); return params; } }; requestQueue2.add(jsArrRequest); } public void clear() { int size = newMallModels.size(); newMallModels.clear(); Log.i("LOL", String.valueOf(size)); } public void GET_MALL_PARSE(JSONArray array) { clear(); for (int i = 0; i < array.length(); i++) { ModelMall GetMallDataModel = new ModelMall(); Log.i("SUCCESS", "Event web call success"); JSONObject json = null; try { json = array.getJSONObject(i); GetMallDataModel.setMallId(json.getString("$id")); GetMallDataModel.setMallName(json.getString("Resourcetype_en")); newMallModels.add(GetMallDataModel); } catch (JSONException e) { e.printStackTrace(); } } // 更新Activity内的适配器(如果保留的话) if (array.length() != 0 && mallRecyclerAdapter != null) { mallRecyclerAdapter.updateModels(newMallModels); } // 如果Popup已显示,同步更新数据 if (currentPopupWindow != null && currentPopupWindow.isShowing()) { View popupView = currentPopupWindow.getContentView(); RecyclerView popupRecyclerView = popupView.findViewById(R.id.recyclerView); MallAdapter adapter = (MallAdapter) popupRecyclerView.getAdapter(); adapter.updateModels(newMallModels); } } public void showPopup(View view) { LayoutInflater inflater = (LayoutInflater) view.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View popupView = inflater.inflate(R.layout.layout_mall_recycler, null); int width = LinearLayout.LayoutParams.MATCH_PARENT; int height = LinearLayout.LayoutParams.MATCH_PARENT; boolean focusable = true; currentPopupWindow = new PopupWindow(popupView, width, height, focusable); // 初始化Popup内的RecyclerView RecyclerView popupRecyclerView = popupView.findViewById(R.id.recyclerView); LinearLayoutManager popupLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); popupRecyclerView.setLayoutManager(popupLayoutManager); MallAdapter popupAdapter = new MallAdapter(this); popupAdapter.updateModels(newMallModels); // 传入已加载的数据 popupRecyclerView.setAdapter(popupAdapter); currentPopupWindow.showAtLocation(view, Gravity.CENTER, 0, 0); popupView.setOnTouchListener((v, event) -> { currentPopupWindow.dismiss(); currentPopupWindow = null; return true; }); } // 新增:供适配器调用关闭Popup public void dismissPopup() { if (currentPopupWindow != null && currentPopupWindow.isShowing()) { currentPopupWindow.dismiss(); currentPopupWindow = null; } } private void saveInSp(String key, String value) { SharedPreferences preferences = getApplicationContext().getSharedPreferences("PROJECT_NAME", Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putString(key, value); editor.apply(); } private String getFromSP(String key) { SharedPreferences preferences = this.getSharedPreferences("PROJECT_NAME", Context.MODE_PRIVATE); return preferences.getString(key, ""); } @Override protected void onResume() { super.onResume(); } }
MallAdapter.java
public class MallAdapter extends RecyclerView.Adapter<MallAdapter.ViewHolder> { private Context context; private final List<ModelMall> mallDataModels; private static ProgressDialog mProgressDialog; public MallAdapter(Context context) { super(); this.context = context; this.mallDataModels = new ArrayList<>(); } public void updateModels(List<ModelMall> newModels) { mallDataModels.clear(); mallDataModels.addAll(newModels); notifyDataSetChanged(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item_layout, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder viewHolder, final int position) { final ModelMall dataAdapter = mallDataModels.get(position); viewHolder.tVMallName.setText(dataAdapter.getMallName()); // 修正:点击Item时保存选中值并关闭Popup viewHolder.itemView.setOnClickListener(v -> { saveInSp("SelectedMallName", dataAdapter.getMallId()); // 关闭Popup if (context instanceof SetupActivity) { ((SetupActivity) context).dismissPopup(); } }); } private static void removeSimpleProgressDialog() { try { if (mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); mProgressDialog = null; } } catch (Exception ie) { ie.printStackTrace(); } } public static void showSimpleProgressDialog(Context context, String title, String msg, boolean isCancelable) { try { if (mProgressDialog == null) { mProgressDialog = ProgressDialog.show(context, title, msg); mProgressDialog.setCancelable(isCancelable); } else if (!mProgressDialog.isShowing()) { mProgressDialog.show(); } } catch (Exception ie) { ie.printStackTrace(); } } @Override public int getItemCount() { return mallDataModels.size(); } private void saveInSp(String key, String value) { SharedPreferences preferences = context.getSharedPreferences("PROJECT_NAME", Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putString(key, value); editor.apply(); } class ViewHolder extends RecyclerView.ViewHolder { private TextView tVMallName; public ViewHolder(View itemView) { super(itemView); tVMallName = itemView.findViewById(R.id.textMallName); } } }
popup_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:paddingLeft="10dp" android:paddingRight="10dp"> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardCornerRadius="5dp"> <LinearLayout android:id="@+id/recyclerLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/value40_50_60" android:background="@drawable/recycle_box" android:orientation="vertical"> <TextView android:id="@+id/text1" style="@style/selectOne" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="40dp" android:background="@drawable/recycle_select_box" android:fontFamily="@font/four_c_seven" android:gravity="center" android:text="Select Mall" android:textColor="#fff" android:textSize="@dimen/value12_16_20" android:textStyle="bold" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" style="@style/selectOne" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="40dp" android:orientation="vertical" android:visibility="visible" tools:itemCount="20" tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager" tools:listitem="@layout/recycler_item_layout" /> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout>
核心解决方案说明
网络请求时机:
- 方案一:Activity启动时调用
GET_MALL_WEB_CALL()预加载数据,用户点击弹窗时直接展示 - 方案二:点击EditText时检查数据是否为空,为空则发起请求并显示加载弹窗,加载完成后自动弹出Popup
- 方案一:Activity启动时调用
PopupWindow内RecyclerView初始化:
- 在
showPopup()方法中,通过popupView.findViewById()获取Popup内的RecyclerView - 初始化布局管理器和适配器,调用
updateModels()传入全局集合newMallModels的数据,最后设置适配器
- 在
数据同步更新:
- 网络请求完成后更新全局
newMallModels,如果Popup已显示,直接获取Popup内的适配器并调用updateModels()刷新数据
- 网络请求完成后更新全局
优化方案:
- 使用
LiveData监听newMallModels变化,自动更新所有关联的RecyclerView,无需手动调用刷新方法 - 将PopupWindow封装为独立类,传入数据和点击回调,降低与Activity的耦合度
- 给Popup内的RecyclerView添加Item点击事件,选中后自动关闭Popup并保存选中值
- 使用
内容的提问来源于stack exchange,提问作者Kumza Ion
相关产品推荐
相关产品推荐

