在ValueEventListener中初始化后,全局variables的值将被重置

我有一个名为“bg”的全局variables。 它在Firebase数据库引用“myRef”的ValueEventListener内被初始化

但是,如果我尝试使用valueeventlistener块外部的variables的值,该variables是空的。 就好像它正在重置。

我对android非常陌生。 请让我知道什么是错的。

代码如下:

package com.example.tejasvi.donorfinder; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.widget.Toast; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; public class MapsActivity extends FragmentActivity implements OnMapReadyCallback { private GoogleMap mMap; private FirebaseAuth mAuth; public String latlng[],bg; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); mAuth = FirebaseAuth.getInstance(); Bundle bundle = getIntent().getExtras(); String s= bundle.getString("Phone"); String path="Active Requests/"+mAuth.getCurrentUser().getUid()+"/"+s+"/Blood Group"; FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference myRef = database.getReference(path); myRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { bg=dataSnapshot.getValue().toString(); } @Override public void onCancelled(DatabaseError databaseError) { Toast.makeText(MapsActivity.this, "Error", Toast.LENGTH_LONG).show(); } }); Toast.makeText(MapsActivity.this, bg, Toast.LENGTH_SHORT).show(); //bg is empty here SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; } } 

dataSnapshot.getValue()的值是“A + ve”

JSON文件如下所示:

 { "Active Requests": { "3R8XGIM5uSRv3sxQZ2sqqUnIjQ62": { "9849949799": { "Blood Group": "B+ve", "Date of Requirement": "3/1/17", "Direct or Replacement?": "Direct donation", "Donation Type": "Whole Blood", "For Self?": "Yes", "Hospital Name": "Shekhar Hospital", "Location": "12.945793000000002,77.56759339999999", "Name": "Poorna Chandra Tejasvi", "Units": "2" } }, "YL5oVxmua4gktNM2TwwPavL1Tj32": { "123456789": { "Blood Group": "A+ve", "Date of Requirement": "1/1/17", "Direct or Replacement?": "Direct donation", "Donation Type": "Whole Blood", "For Self?": "No", "Hospital Name": "Columbia Asia Hospital - Hebbal", "Location": "13.0509869,77.5937892", "Recipient Name": "jssnxn", "Recipient Relation": "Married", "Units": "3" } } } } 

这里没有魔法。 你只是看到了asynchronous加载的影响,大多数的现代networkingbuild立在这种影响之上。

如果您在debugging器中运行代码或添加一些日志logging语句,这是最容易理解的,如下所示:

 FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference myRef = database.getReference(path); System.out.println("Before adding listener"); myRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { System.out.println("In onDataChange"); } @Override public void onCancelled(DatabaseError databaseError) { throw databaseError.toException(); } }); System.out.println("After adding listener"); 

当你像这样运行代码时,它会打印:

添加监听器之前

添加监听器之后

在OnDataChange中

这可能不是您所期望的,但这是在处理Firebase和所谓的最现代的Web API时的预期行为。 由于加载数据可能需要一段时间(它必须从互联网上的某个地方得到),代码不会等待数据的返回,而只需要在连接后继续使用该行监听器。 然后当数据变得可用时,它调用你的onDataChange() ,你可以使用这些数据。

这个行为起初是令人难以置信的混乱,所以不要担心,如果它不立即明确。 重要的是要认识到,行为是正常的,是现代networking编程的一部分。 所以不要试图解决它(即使代码等待数据)。 相反:尝试将你的问题重构成一个更好的asynchronous性质的模型。

我发现从“首先加载数据,然后在烤面包中显示”到“开始加载数据,然后在加载时,将其显示在烤面包中”这个问题,我很容易将其重新devise。 这转换为以下代码:

 FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference myRef = database.getReference(path); myRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { bg=dataSnapshot.getValue().toString(); Toast.makeText(MapsActivity.this, bg, Toast.LENGTH_SHORT).show(); } @Override public void onCancelled(DatabaseError databaseError) { throw databaseError.toException(); } });