英文:
Can't get onDataChange to run first in Android
问题
这个活动在地图上显示地理围栏。它们作为对象添加到ArrayList中,然后被initArea()
使用,并显示在地图上。我的问题是initArea()
在onDataChange()
之前运行,因此没有将任何内容添加到ArrayList中,并且会抛出空指针异常。我希望onDatachange()
先运行,以便ArrayList被填充。提前感谢
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GeoQueryEventListener {
private static final String TAG = "Maps";
private GoogleMap mMap;
private LocationRequest locationRequest;
private LocationCallback locationCallback;
private FusedLocationProviderClient fusedLocationProviderClient;
private Marker currentLocation;
private DatabaseReference locationRef;
private GeoFire geofire;
private List<LatLng> geoFence;
ArrayList<geofenceObj> geoTemp = new ArrayList<>();
private String userID;
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;
private int check;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
myRef = mFirebaseDatabase.getReference();
FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// 用户已登录
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// 用户已注销
Log.d(TAG, "onAuthStateChanged:signed_out");
}
}
};
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// 此方法在初始值和每次在此位置的数据更新时调用。
showData(dataSnapshot);
initArea(); // 在这里调用initArea(),以确保在数据变化后初始化区域。
}
@Override
public void onCancelled(DatabaseError databaseError) {
// 处理数据库错误
}
});
// ... 其他代码
}
// ... 其他方法
}
英文:
This activity displays geofences to the map. They're added as objects to an arraylist and then used by initArea() and are shown on the map. My issue is initArea() runs before onDataChange() so nothing is added to the arraylist and a null pointer exception is thrown. I want onDatachange() to run first so that the arraylist is populated. Thanks in advance
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GeoQueryEventListener {
private static final String TAG = "Maps";
private GoogleMap mMap;
private LocationRequest locationRequest;
private LocationCallback locationCallback;
private FusedLocationProviderClient fusedLocationProviderClient;
private Marker currentLocation;
private DatabaseReference locationRef;
private GeoFire geofire;
private List<LatLng> geoFence;
ArrayList<geofenceObj> geoTemp = new ArrayList<>();
private String userID;
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;
private int check;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
myRef = mFirebaseDatabase.getReference();
FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
}
};
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
showData(dataSnapshot);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
Dexter.withActivity(this)
.withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(new PermissionListener() {
@Override
public void onPermissionGranted(PermissionGrantedResponse response) {
buildLocationRequest();
buildlocationcallback();
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(MapsActivity.this);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(MapsActivity.this);
initArea();
settingGeofire();
}
@Override
public void onPermissionDenied(PermissionDeniedResponse response) {
Toast.makeText(MapsActivity.this, "Permissions not enabled ", Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
}
}).check();
}
private void showData(DataSnapshot dataSnapshot) {
geoTemp.clear();
for(DataSnapshot i : dataSnapshot.getChildren()) {
for(int j=1; j<=dataSnapshot.child("users").child(userID).getChildrenCount(); j++) {
String ID = String.valueOf(j);
if (i.child(userID).child(ID).getValue() != null) {
geofenceObj geofence = new geofenceObj();
geofence.setName(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getName());
geofence.setRadius(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getRadius());
geofence.setLat(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLat());
geofence.setLng(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLng());
geoTemp.add(geofence);
Log.d(TAG, "Added " + geofence.getName());
}
}
}
}
private void initArea() {
geoFence = new ArrayList<>();
geoFence.add(new LatLng(0, 0));
for(int i = 0; i <= geoTemp.size(); i++){
geoFence.add(new LatLng(geoTemp.get(i).getLat(), geoTemp.get(i).getLat()));
}
Log.d(TAG, "Initialised Area");
}
答案1
得分: 0
你无法改变异步数据加载的顺序。但你可以改变的是初始化依赖于数据的地图的时间点。所以将调用 initArea()
的代码移到 onDataChange
(或者 showData
)方法中,以确保它在数据加载完成后运行。
private void showData(DataSnapshot dataSnapshot) {
geoTemp.clear();
for (DataSnapshot i : dataSnapshot.getChildren()) {
for (int j = 1; j <= dataSnapshot.child("users").child(userID).getChildrenCount(); j++) {
String ID = String.valueOf(j);
if (i.child(userID).child(ID).getValue() != null) {
geofenceObj geofence = new geofenceObj();
geofence.setName(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getName());
geofence.setRadius(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getRadius());
geofence.setLat(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLat());
geofence.setLng(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLng());
geoTemp.add(geofence);
Log.d(TAG, "Added " + geofence.getName());
}
}
}
// 数据加载和处理完成后,现在可以初始化地图
initArea();
}
英文:
You can't change the order in which asynchronous data is loaded. But what you can change is when you initialize the map that depends on the data. So move the call to initArea()
into the onDataChange
(or the showData
) method, so that is runs after the data has been loaded.
private void showData(DataSnapshot dataSnapshot) {
geoTemp.clear();
for(DataSnapshot i : dataSnapshot.getChildren()) {
for(int j=1; j<=dataSnapshot.child("users").child(userID).getChildrenCount(); j++) {
String ID = String.valueOf(j);
if (i.child(userID).child(ID).getValue() != null) {
geofenceObj geofence = new geofenceObj();
geofence.setName(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getName());
geofence.setRadius(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getRadius());
geofence.setLat(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLat());
geofence.setLng(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLng());
geoTemp.add(geofence);
Log.d(TAG, "Added " + geofence.getName());
}
}
}
// Now that the data is loaded and processed, we can initialize the map
initArea();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论