2017-10-29 132 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)){