FirebaseListAdapter空指针异常:大学聊天应用启动崩溃修复求助
修复FirebaseListAdapter空指针导致的Activity崩溃问题
嘿,这问题我熟!你遇到的空指针异常根源很明确:onStart()方法执行时,FirebaseListAdapter实例还没被初始化。
看你的代码就知道,adapter只有在点击FloatingActionButton的时候才会调用displayChatMessage()去创建,但onStart()是Activity启动时就会触发的生命周期方法,这时候adapter还是null,调用adapter.startListening()自然就炸了。
具体修复步骤:
- 提前初始化Adapter:在用户登录成功的逻辑里就调用
displayChatMessage(),而不是等点击fab才初始化 - 覆盖登录成功的场景:不管是已登录直接进入页面,还是登录界面返回成功,都要确保Adapter被创建
- 可选优化:把ListView的初始化移到
onCreate()里,避免重复调用findViewById
修改后的代码示例:
public class ActivityChat extends AppCompatActivity { private static int SIGN_IN_REQUEST_CODE = 1; private FirebaseListAdapter<ChatMsg> adapter; Query query = FirebaseDatabase.getInstance().getReference().child("Chats").limitToLast(50); FirebaseListOptions<ChatMsg> options = new FirebaseListOptions.Builder<ChatMsg>() .setQuery(query, ChatMsg.class) .setLayout(R.layout.message_item) // 注意!这里应该是单个消息的item布局,不是Activity的布局! .build(); EditText input; RelativeLayout chat; FloatingActionButton fab; ListView listMessage; // 提前声明ListView @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == SIGN_IN_REQUEST_CODE) { if (resultCode == RESULT_OK) { Toast.makeText(getApplicationContext(), "Pomyślnie zalogowany!", Toast.LENGTH_SHORT).show(); // 登录成功后立即初始化Adapter displayChatMessage(); } else { Toast.makeText(getApplicationContext(), "Nie można zalogować się. Spróbuj później.", Toast.LENGTH_SHORT).show(); finish(); // 登录失败可以关闭聊天页面 } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); input = (EditText) findViewById(R.id.input); chat = (RelativeLayout) findViewById(R.id.activity_chat); fab = (FloatingActionButton) findViewById(R.id.fab); listMessage = (ListView) findViewById(R.id.list_of_message); // 提前初始化ListView fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(FirebaseAuth.getInstance().getCurrentUser() == null) return; // 加个安全判断 FirebaseDatabase.getInstance().getReference("Chats").push().setValue(new ChatMsg(input.getText().toString(), FirebaseAuth.getInstance().getCurrentUser().getEmail())); input.setText(""); input.requestFocus(); // 这里不需要再调用displayChatMessage了,Adapter已经初始化过 } }); if (FirebaseAuth.getInstance().getCurrentUser() == null) { startActivityForResult(AuthUI.getInstance().createSignInIntentBuilder().build(), SIGN_IN_REQUEST_CODE); } else { Toast.makeText(getApplicationContext(), "Witaj: " + FirebaseAuth.getInstance().getCurrentUser().getEmail(), Toast.LENGTH_SHORT).show(); // 已登录状态下直接初始化Adapter displayChatMessage(); } } private void displayChatMessage() { adapter = new FirebaseListAdapter<ChatMsg>(options) { @Override protected void populateView(@NonNull View v, @NonNull ChatMsg model, int position) { TextView messageText, messageUser, messageTime; messageText = (TextView) v.findViewById(R.id.message_text); messageUser = (TextView) v.findViewById(R.id.message_user); messageTime = (TextView) v.findViewById(R.id.message_time); messageText.setText(model.getMessageText()); messageUser.setText(model.getMessageUser()); messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)", model.getMessageTime())); } }; listMessage.setAdapter(adapter); } @Override protected void onStart() { super.onStart(); // 加个空判断,双重保险 if(adapter != null) { adapter.startListening(); } } @Override protected void onStop() { super.onStop(); if(adapter != null) { adapter.stopListening(); } } }
额外注意点:
我发现你在FirebaseListOptions里设置的setLayout(R.layout.activity_chat),这大概率是个错误!这里应该传入单个聊天消息的item布局(比如R.layout.message_item),而不是Activity的布局文件,否则会导致布局渲染异常,这也是潜在的问题哦。
这样修改后,不管是用户已登录直接进入页面,还是登录成功返回,adapter都会被提前初始化,onStart()调用startListening()时就不会出现空指针了。
内容的提问来源于stack exchange,提问作者user10665228
相关产品推荐
相关产品推荐

