ChildEventListener 未正确填充列表视图
ChildEventListener not populating listview properly
我正在尝试使用 Firebase 中的 ChildEventListener 来使用每个子节点的 "title" 字段填充 listView。但它不能正常工作。我的第一个 activity 是 AuthActivity,其中包含 googleSignIn 按钮,用户可以通过该按钮登录或验证。之后,在 MainActivity 中,一个 listView 应该使用 ChildEventListener datasnapshot 填充数据。但它仍然是空白的。
有趣的部分是,如果我返回 AuthActivity 并按下后退按钮并再次单击登录按钮,它再次将我带到 MainActivity,这次它以某种方式显示了带有正确数据的 listView。关闭应用程序后,会发生同样的错误。 我在 Logcat 中没有收到任何错误。
这是我的 AuthActivity 文件
public class AuthActivity extends AppCompatActivity {
public static final int RC_SIGN_IN = 100;
SignInButton signInButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auth);
signInButton = findViewById(R.id.signInButton);
signInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Choose authentication providers
List<AuthUI.IdpConfig> providers = Arrays.asList(
new AuthUI.IdpConfig.GoogleBuilder().build());
// Create and launch sign-in intent
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.build(),
RC_SIGN_IN);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
if (resultCode == RESULT_OK) {
Intent intent = new Intent(AuthActivity.this, MainActivity.class);
startActivity(intent);
} else {
Toast.makeText(this, "Login Failed! Please try again.", Toast.LENGTH_LONG).show();
}
}
}
}
和 MainActivity 文件
public class MainActivity extends AppCompatActivity {
public static final int RC_SIGN_IN = 100;
ListView listView;
ArrayList<String> titlesArray;
FirebaseDatabase database;
DatabaseReference databaseReference;
FirebaseUser user;
ChildEventListener childEventListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listView);
titlesArray = new ArrayList();
//Get the associated login user info
user = FirebaseAuth.getInstance().getCurrentUser();
//Write a message to the database
database = FirebaseDatabase.getInstance();
databaseReference = database.getReference().child("notes").child(user.getUid());
//Adding adapter to the list of titles
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titlesArray);
listView.setAdapter(adapter);
childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Note notes = dataSnapshot.getValue(Note.class);
titlesArray.add(notes.getTitle());
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Toast.makeText(MainActivity.this, "Loading failed!", Toast.LENGTH_SHORT).show();
}
};
databaseReference.addChildEventListener(childEventListener);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.sign_out_menu:
AuthUI.getInstance()
.signOut(this);
return true;
case R.id.add_new:
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
这是因为您在从 firebase 回调中获取数据后没有通知适配器。
只需像下面那样替换您的侦听器。
childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Note notes = dataSnapshot.getValue(Note.class);
titlesArray.add(notes.getTitle());
adapter.notifyDataSetChanged();
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Toast.makeText(MainActivity.this, "Loading failed!", Toast.LENGTH_SHORT).show();
}
};
我正在尝试使用 Firebase 中的 ChildEventListener 来使用每个子节点的 "title" 字段填充 listView。但它不能正常工作。我的第一个 activity 是 AuthActivity,其中包含 googleSignIn 按钮,用户可以通过该按钮登录或验证。之后,在 MainActivity 中,一个 listView 应该使用 ChildEventListener datasnapshot 填充数据。但它仍然是空白的。
有趣的部分是,如果我返回 AuthActivity 并按下后退按钮并再次单击登录按钮,它再次将我带到 MainActivity,这次它以某种方式显示了带有正确数据的 listView。关闭应用程序后,会发生同样的错误。 我在 Logcat 中没有收到任何错误。
这是我的 AuthActivity 文件
public class AuthActivity extends AppCompatActivity {
public static final int RC_SIGN_IN = 100;
SignInButton signInButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auth);
signInButton = findViewById(R.id.signInButton);
signInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Choose authentication providers
List<AuthUI.IdpConfig> providers = Arrays.asList(
new AuthUI.IdpConfig.GoogleBuilder().build());
// Create and launch sign-in intent
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.build(),
RC_SIGN_IN);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
if (resultCode == RESULT_OK) {
Intent intent = new Intent(AuthActivity.this, MainActivity.class);
startActivity(intent);
} else {
Toast.makeText(this, "Login Failed! Please try again.", Toast.LENGTH_LONG).show();
}
}
}
}
和 MainActivity 文件
public class MainActivity extends AppCompatActivity {
public static final int RC_SIGN_IN = 100;
ListView listView;
ArrayList<String> titlesArray;
FirebaseDatabase database;
DatabaseReference databaseReference;
FirebaseUser user;
ChildEventListener childEventListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listView);
titlesArray = new ArrayList();
//Get the associated login user info
user = FirebaseAuth.getInstance().getCurrentUser();
//Write a message to the database
database = FirebaseDatabase.getInstance();
databaseReference = database.getReference().child("notes").child(user.getUid());
//Adding adapter to the list of titles
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titlesArray);
listView.setAdapter(adapter);
childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Note notes = dataSnapshot.getValue(Note.class);
titlesArray.add(notes.getTitle());
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Toast.makeText(MainActivity.this, "Loading failed!", Toast.LENGTH_SHORT).show();
}
};
databaseReference.addChildEventListener(childEventListener);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.sign_out_menu:
AuthUI.getInstance()
.signOut(this);
return true;
case R.id.add_new:
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
这是因为您在从 firebase 回调中获取数据后没有通知适配器。
只需像下面那样替换您的侦听器。
childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Note notes = dataSnapshot.getValue(Note.class);
titlesArray.add(notes.getTitle());
adapter.notifyDataSetChanged();
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Toast.makeText(MainActivity.this, "Loading failed!", Toast.LENGTH_SHORT).show();
}
};