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

GeoQuery的onKeyEntered中调用buildCardView无法显示CardView的问题

问题

开发就近租车APP,实现找到最近车辆时创建包含TextView和ImageView的CardView。编写了buildCardView方法,直接调用时能正常显示CardView,但在GeoQuery的onKeyEntered回调中调用该方法时,虽然确认方法已执行,CardView却无法显示。

相关代码

触发查询的按钮点击事件

FindCar.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        findClosestCars();
    }
});

Firebase GeoQuery查询方法

private void findClosestCars() {
    if (ActivityCompat.checkSelfPermission(RentersMenuPageActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

        databaseReference = FirebaseDatabase.getInstance().getReference("Users").child("Lenders");
        GeoFire geoFire = new GeoFire(databaseReference);
        GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), radius);
        geoQuery.removeAllListeners();

        geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
            @Override
            public void onKeyEntered(String key, GeoLocation location) {
                if (!driverFound) {
                    driverFound = true;
                    driverFoundID = key;

                    closestLender = FirebaseDatabase.getInstance().getReference("Users").child("Lenders").child(driverFoundID);
                    buildCardView();
                }
                radius++;
            }

            // 需补充实现GeoQueryEventListener的其他抽象方法
            @Override
            public void onKeyExited(String key) {}

            @Override
            public void onKeyMoved(String key, GeoLocation location) {}

            @Override
            public void onGeoQueryReady() {}

            @Override
            public void onGeoQueryError(DatabaseError error) {}
        });
    }
}

CardView创建方法

private void buildCardView(){
    Toast.makeText(RentersMenuPageActivity.this, "You Found a Lender",Toast.LENGTH_LONG).show();

    LayoutInflater mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    View view = getLayoutInflater().inflate(R.layout.card, null);

    Button rentCarButton = view.findViewById(R.id.rentCarButton);
    TextView price= view.findViewById(R.id.price);
    TextView makeandmodel = view.findViewById(R.id.makeandmodel);
    ImageView imageView = view.findViewById(R.id.imageViewScroll);

    LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT);
    linearLayout.addView(view);
}

解决方案

问题核心:Android所有UI操作必须在主线程执行,而Firebase GeoQuery的onKeyEntered回调运行在后台线程,直接调用buildCardView添加View不会触发UI刷新。

修复方式1:在buildCardView内部切换到主线程

修改buildCardView方法,将所有UI操作包裹在runOnUiThread中:

private void buildCardView(){
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(RentersMenuPageActivity.this, "You Found a Lender",Toast.LENGTH_LONG).show();

            LayoutInflater mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            View view = getLayoutInflater().inflate(R.layout.card, null);

            Button rentCarButton = view.findViewById(R.id.rentCarButton);
            TextView price= view.findViewById(R.id.price);
            TextView makeandmodel = view.findViewById(R.id.makeandmodel);
            ImageView imageView = view.findViewById(R.id.imageViewScroll);

            LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT);
            linearLayout.addView(view);
        }
    });
}

修复方式2:在onKeyEntered中调用时切换到主线程

保持buildCardView不变,在回调中用runOnUiThread包裹调用:

@Override
public void onKeyEntered(String key, GeoLocation location) {
    if (!driverFound) {
        driverFound = true;
        driverFoundID = key;
        closestLender = FirebaseDatabase.getInstance().getReference("Users").child("Lenders").child(driverFoundID);
        
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                buildCardView();
            }
        });
    }
    radius++;
}

说明

通过runOnUiThread将UI操作切换到主线程后,系统会正确处理View的添加和刷新,CardView就能正常显示了。

内容的提问来源于stack exchange,提问作者Timothy Smith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:50:14