2017-10-29 118 views
0

我正在做一个来自在线教程的实时跟踪应用程序,在这里我使用firebase设置存在系统。DataSnapShot对象的值在getvalue上返回null(Boolean.class)

/java.lang.NullPointerException:尝试在空对象引用调用虚方法“布尔java.lang.Boolean.booleanValue()”

我不明白什么,但它与崩溃编码这个人的人错了,它的工作很完美。

该异常正在发生在这条线:如果(dataSnapshot.getValue(Boolean.class)){

当我记录此屏幕上的datasnapshot对象具有键但没有值

帮助!

ListOnline类

//firebase 
DatabaseReference onlineRef,currentUserRef,counterRef; 
FirebaseRecyclerAdapter<User,ListOnlineViewHolder> adapter; 

//View 
RecyclerView listOnline; 
RecyclerView.LayoutManager layoutManager; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_list_online); 

    //setting the recyclerview 
    listOnline = (RecyclerView)findViewById(R.id.listOnlineRecyclerview); 
    listOnline.setHasFixedSize(true); 
    layoutManager = new LinearLayoutManager(this); 
    listOnline.setLayoutManager(layoutManager); 

    //set toolbar and menu/join,logout 
    Toolbar toolbar = (Toolbar)findViewById(R.id.toolbarID); 
    toolbar.setTitle("Presence System"); 
    setSupportActionBar(toolbar); 

    //firebase 
    onlineRef = FirebaseDatabase.getInstance().getReference().child("info/connected"); 
    counterRef = FirebaseDatabase.getInstance().getReference("lastOnline"); //create new child name lastOnline 
    currentUserRef = FirebaseDatabase.getInstance().getReference().child(FirebaseAuth.getInstance().getCurrentUser().getUid()); 

    setupSystem(); 
    //after setup we load all users and display in recyclerview 
    //this is online list 
    updateList(); 
} 

private void updateList() { 
    adapter = new FirebaseRecyclerAdapter<User, ListOnlineViewHolder>(
      User.class,R.layout.user_layout,ListOnlineViewHolder.class,counterRef 
    ) { 
     @Override 
     protected void populateViewHolder(ListOnlineViewHolder viewHolder, User model, int position) { 
      viewHolder.emailTextView.setText(model.getEmail()); 
     } 

    }; 
    adapter.notifyDataSetChanged(); 
    listOnline.setAdapter(adapter); 
} 

private void setupSystem() { 
    onlineRef.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
       if(dataSnapshot.getValue(Boolean.class)){ 
        currentUserRef.onDisconnect().removeValue(); 
        //set online user in list 
        counterRef.child(FirebaseAuth.getInstance().getCurrentUser().getUid()) 
          .setValue(FirebaseAuth.getInstance().getCurrentUser().getEmail(),"Online"); 
        adapter.notifyDataSetChanged(); 
       } 
      } 



     @Override 
     public void onCancelled(DatabaseError databaseError) { 

     } 
    }); 
    counterRef.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      for(DataSnapshot postSnapshot:dataSnapshot.getChildren()){ 
       User user = postSnapshot.getValue(User.class); 
       Log.d("LOG",""+user.getEmail()+"is "+user.getStatus()); 
      } 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 

     } 
    }); 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater menuInflater = getMenuInflater(); 
    menuInflater.inflate(R.menu.main_menu,menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()){ 
     case R.id.action_join: 
      counterRef.child(FirebaseAuth.getInstance().getCurrentUser().getUid()) 
        .setValue(FirebaseAuth.getInstance().getCurrentUser().getEmail(),"Online"); 
      break; 
     case R.id.action_logout: 
      currentUserRef.removeValue(); 

    } 
    return super.onOptionsItemSelected(item); 
} 

}

用户类

public class User { 
private String email,status; 


public User(String email, String status) { 
    this.email = email; 
    this.status = status; 
} 

public User() { 

} 

public String getEmail() { 
    return email; 
} 

public void setEmail(String email) { 
    this.email = email; 
} 

public String getStatus() { 
    return status; 
} 

public void setStatus(String status) { 
    this.status = status; 
}} 

MainActivity

public class MainActivity extends AppCompatActivity { 

Button signInButton; 
private final static int LOGIN_PERMISSION = 1000; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    signInButton = (Button) findViewById(R.id.signInButton); 
    signInButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      startActivityForResult(AuthUI.getInstance().createSignInIntentBuilder().setAllowNewEmailAccounts(true).build(),LOGIN_PERMISSION); 

     } 

    }); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 

    if(requestCode == LOGIN_PERMISSION){ 
     startNewActivity(resultCode,data); 
    } 
} 

private void startNewActivity(int resultcode, Intent data) { 

    if(resultcode == RESULT_OK){ 
     Intent intent = new Intent(MainActivity.this,ListOnline.class); 
     startActivity(intent); 
     finish(); 

    } 
    else{ 
     Toast.makeText(this,"login failed!!",Toast.LENGTH_SHORT).show(); 
    } 
}} 
+0

[?什么是空指针异常,以及如何解决呢(https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and如何做我修复它) – Grimthorr

+0

@Grimthorr谢谢,但没有帮助 – Akay

回答

0

在你setupSystem()方法,要附加一个监听器onlineRef(在info/connected节点),然后是编组返回值给一个Boolean值。如果数据库中指定位置没有数据,则DataSnapshot#getValue()将返回null。如果发生这种情况,dataSnapshot.getValue(Boolean.class)调用将创建一个Boolean变量,其值为null,然后无法在当前的if语句中检查真值(请参阅Check if null Boolean is true results in exception)。

你可以检查getValue()不通过添加一个空检查你的if语句返回null第一:

if(dataSnapshot.getValue() != null && dataSnapshot.getValue(Boolean.class)){ 
    // ... 
} 

或者检查该位置存在使用DataSnapshot#exists()

if(dataSnapshot.exists() && dataSnapshot.getValue(Boolean.class)){ 
    // ... 
} 

然而,如果您尝试detect connection state,是不是要将听众附加到.info/connected节点上?从文档:

对于许多存在相关的功能,为您的应用程序知道 当它是在线还是离线它是有用的。 Firebase实时数据库在/.info/connected处提供 特殊位置,每次 Firebase实时数据库客户端的连接状态发生变化时都会更新。下面是 一个例子:

DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected"); 
connectedRef.addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot snapshot) { 
    boolean connected = snapshot.getValue(Boolean.class); 
    if (connected) { 
     System.out.println("connected"); 
    } else { 
     System.out.println("not connected"); 
    } 
    } 

    @Override 
    public void onCancelled(DatabaseError error) { 
    System.err.println("Listener was cancelled"); 
    } 
}); 
+0

我修正了它是一个小的“。”。从info/connected line丢失我有一个新的崩溃,虽然 – Akay

+0

com.google.firebase.database.DatabaseException:无法转换java.lang.String类型的对象: User user = postSnapshot.getValue(User.class) ; – Akay

+0

这将来自您尝试编组为“用户”实例的'/ lastOnline'位置。你能分享你的数据库结构吗?这个位置的值可能与您的User类不匹配。 – Grimthorr

0

其空,因为它不存在于数据库..

onlineRef = FirebaseDatabase.getInstance().getReference().child("info/connected"); 

要查询上述位置。所以dataSnapshot是上述的快照..

if(dataSnapshot.getValue(Boolean.class)){ 

这并不存在于数据库中。因此,你得到这个错误

+0

我该如何解决这个问题?我是一个非常新的firebase,所以不介意我的无知 – Akay

+0

@Akay你的意思是两个用户设置,如老师和学生? –

+0

对不起,我的意思是我有两个用户在数据库中。它怎么可以为null – Akay

0

看来你没有在数据库中的值。这将处理错误

if(dataSnapshot.getValue(Boolean.class) != null && dataSnapshot.getValue(Boolean.class)){