You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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);
        }
    }
}
<?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>

核心解决方案说明
  1. 网络请求时机:

    • 方案一:Activity启动时调用GET_MALL_WEB_CALL()预加载数据,用户点击弹窗时直接展示
    • 方案二:点击EditText时检查数据是否为空,为空则发起请求并显示加载弹窗,加载完成后自动弹出Popup
  2. PopupWindow内RecyclerView初始化:

    • 在showPopup()方法中,通过popupView.findViewById()获取Popup内的RecyclerView
    • 初始化布局管理器和适配器,调用updateModels()传入全局集合newMallModels的数据,最后设置适配器
  3. 数据同步更新:

    • 网络请求完成后更新全局newMallModels,如果Popup已显示,直接获取Popup内的适配器并调用updateModels()刷新数据
  4. 优化方案:

    • 使用LiveData监听newMallModels变化,自动更新所有关联的RecyclerView,无需手动调用刷新方法
    • 将PopupWindow封装为独立类,传入数据和点击回调,降低与Activity的耦合度
    • 给Popup内的RecyclerView添加Item点击事件,选中后自动关闭Popup并保存选中值

内容的提问来源于stack exchange,提问作者Kumza Ion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:45:47