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
相关产品推荐
相关产品推荐

