问题
I have some global variables whose values need to be updated dynamically as per the database contains.
So I tried using ValueEventListener()
I can successfully read the intended value and show that in the Log.
But unfortunately when I try to store that value in the previously declared some global variable it dose not work m though it dose not show any error, but it dose fail to store the intended value(I am giving the code where , you can find a Log message to show the size of the list after updation through ValueEventListener()
and its output still shows 0..
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private String RxuserId;
private String currentuserName;
private String currentuser,path;
public ArrayList<String> mToken;
private FirebaseDatabase database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//for keeping the keyboard hidden
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Intent intent=getIntent();
RxuserId=intent.getStringExtra("Id");
Rxusrnm=intent.getStringExtra("Name");
//storeName(usrnm);
currentuserName=SharedPrefManager.getmInstnce(this).getUsername();
currentuser=SharedPrefManager.getmInstnce(this).getUserID();
database = FirebaseDatabase.getInstance();
providers = new ArrayList<>();
mToken = new ArrayList<>();
if(RxuserId!=null){
database.getReference().child("users").child(RxuserId).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mToken.add(dataSnapshot.child("fcm token").getValue().toString());
mToken.add("nsks");
Toast.makeText(getApplicationContext(),"REQUIRED TOKRN "+dataSnapshot.child("fcm token").getValue().toString(),Toast.LENGTH_LONG).show();
Log.d(TAG,"REQUIRED TOKRN "+dataSnapshot.child("fcm token").getValue().toString());
//These two are shown correctly
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
Log.d(TAG,"REQUIRED TOKRN "+mToken.size())//which shows 0 ;
}
where am I doing wrong? and what should I do such that I can update the value of a global variable from inside a ValueEventListener()
?
Thank you
回答1:
Firebase's ValueEventListener works asynchronously. That is why your logging code at the end, prints earlier than your asynchronous listener gets triggered. Data from firebase is indeed added(reflected) to the global variable, but after the log.
If you want to do some logic when firebase data changes you should do your logic directly inside the ValueEventListener or use LiveData or RxJava.
Here how to use LiveData:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private String RxuserId;
public ArrayList<String> mToken;
MutableLiveData<String> data = new MutableLiveData<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RxuserId = intent.getStringExtra("Id");
mToken = new ArrayList<>();
if(RxuserId != null){
database.getReference().child("users").child(RxuserId).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
data.setValue(dataSnapshot.child("fcm token").getValue().toString());
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
data.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
mToken.add(s);
Toast.makeText(getApplicationContext(), "REQUIRED TOKRN " + s,Toast.LENGTH_LONG).show();
Log.d(TAG,"REQUIRED TOKRN " + string);
Log.d(TAG,"REQUIRED TOKRN " + mToken.size())
}
});
}
}
This is not very useful case for LivaData. Usually LiveData is used when the logic with firebse is in another class (in Repository MVVM) to change UI according to data change.
List of users can be stored like this:
// User is model class
List<User> users = new ArrayList<>();
final MutableLiveData<List<User>> data = new MutableLiveData<>();
database.child("users").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<User> users = new ArrayList<>();
for (DataSnapshot ds : dataSnapshot.getChildren()) {
User user = ds.getValue(User.class);
users.add(user);
}
data.setValue(users); // data can be observed later
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
来源:https://stackoverflow.com/questions/56718979/assignments-done-inside-valueeventlisteners-of-firebase-database-is-not-being-re