java.lang.NullPointerException:无法在child()

时间:2018-07-27 05:09:44

标签: java android firebase firebase-realtime-database

Structure of database

enter image description here

首先,在测试用户何时登录或完全注册时,没有异常或错误,但是当用户注销并重新打开应用程序时,应用程序崩溃。 logcat基本上指出了这个错误:

 UsersRef.child(currentUserID).addValueEventListener(new ValueEventListener()

但是,如果我将 currentUserID 更改为 Users ..该应用程序将停止崩溃并顺利运行,但不会加载用户名和位于导航抽屉。

mainactivity.java

public class MainActivity extends AppCompatActivity {
    private NavigationView navigationView;
    private DrawerLayout drawerLayout;
    private RecyclerView postlist;
    private Toolbar mToolbar;
    private ActionBarDrawerToggle actionBarDrawerToggle;
    private FirebaseAuth mAuth;
    private FirebaseUser FirebaseUser;
    private DatabaseReference  UsersRef;
    private CircleImageView NavProfileImage;
    private ImageButton AddNewPostButton;
    private TextView NavProfileUserName;
    String currentUserID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAuth = FirebaseAuth.getInstance();
        final FirebaseUser mFirebaseUser = mAuth.getCurrentUser();
        if (mFirebaseUser != null) {
            currentUserID = mFirebaseUser.getUid();
        }




        mToolbar =(Toolbar) findViewById(R.id.main_page_toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setTitle("Home");

        drawerLayout = (DrawerLayout) findViewById(R.id.drawable_layout);
       actionBarDrawerToggle =  new ActionBarDrawerToggle(MainActivity.this,drawerLayout,R.string.drawer_open, R.string.drawer_close);
        navigationView = (NavigationView)findViewById(R.id.navigation_view);
       AddNewPostButton = (ImageButton)findViewById(R.id.add_new_post_button);

        drawerLayout.addDrawerListener(actionBarDrawerToggle);
       actionBarDrawerToggle.syncState();
       getSupportActionBar().setDisplayHomeAsUpEnabled(true);


        View navView = navigationView.inflateHeaderView(R.layout.nav_header);
        NavProfileImage = (CircleImageView)navView.findViewById(R.id.nav_profile_image);
        NavProfileUserName = (TextView) navView.findViewById(R.id.nav_user_full_name);

        UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
        UsersRef.child(currentUserID).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot)
            {
                if(dataSnapshot.exists())
                {   if (dataSnapshot.hasChild("fullname")){
                    String fullname = dataSnapshot.child("fullname").getValue().toString();
                    NavProfileUserName.setText(fullname);
                }if (dataSnapshot.hasChild("profileimage")) {
                    String image = dataSnapshot.child("profileimage").getValue().toString();
                    Picasso.with(MainActivity.this).load(image).placeholder(R.drawable.profile).into(NavProfileImage);

                }else {
                    Toast.makeText(MainActivity.this, "Profile name do not exists...", Toast.LENGTH_SHORT).show();
                }




                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item)
            { UserMenuSelector(item);

                return false;
            }
        });
        AddNewPostButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SendUserToPostActivity();

            }
        });
    }

    private void SendUserToPostActivity() {
        Intent addNewPostIntent = new Intent (MainActivity.this,PostActivity.class);
        startActivity(addNewPostIntent);
    }

    @Override
    protected void onStart() {
        super.onStart();
        FirebaseUser currentUser = mAuth.getCurrentUser();
        if (currentUser == null)
        {
            sendUserToLoginActivity();
        }else{
            CheckUserExistance();
        }
    }

    private void CheckUserExistance()
    {
        final String current_user_id = mAuth.getCurrentUser().getUid();
          UsersRef.addValueEventListener(new ValueEventListener() {
              @Override
              public void onDataChange(DataSnapshot dataSnapshot) {
                  if (!dataSnapshot.hasChild(current_user_id)){
                      sendUserToSetupActivity();
                  }
              }

              @Override
              public void onCancelled(DatabaseError databaseError) {

              }
          });
    }

    private void sendUserToSetupActivity() {
        Intent setupIntent = new Intent(MainActivity.this, SetupActivity.class);
        setupIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        startActivity(setupIntent);
        finish();

    }

    private void sendUserToLoginActivity()
    {
        Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
         loginIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         startActivity(loginIntent);
         finish();

    }

4 个答案:

答案 0 :(得分:2)

我认为您在null中获得了currentUserId,然后将null传递到了Firebase。可能是您没有获得user id,请确保用户已登录,然后检查您是否从firebase获得了user的ID。如果您是从Firebase获取user id,请尝试执行此操作。

UsersRef.child("Users").child(currentUserID).addValueEventListener(new 
       ValueEventListener(){ }

并确保您的User Model类中的所有键都是公开的,我定期在firebase上工作约一个月,并且遇到了许多类似问题。

答案 1 :(得分:1)

如果您检查一下,我相信您没有任何登录用户,这就是为什么您在null中获得currentUserID值的原因。

您正在检查用户是否登录OnStart(),还必须在onCreate()中进行检查。因为在活动生命周期中,onCreate()onStart()之前被调用。

这是onCreate函数的外观:

@Override
protected void onCreate(Bundle savedInstanceState) {
    FirebaseUser currentUser = mAuth.getCurrentUser();
    if (currentUser == null)
    {
        sendUserToLoginActivity();
    }else{
        CheckUserExistance();
    }
    //Your code ...
}

答案 2 :(得分:1)

注销后mFirebaseUser会得到null值,因此该currentUserID值也将得到null以避免nullpointerexception在使用currentUserID之前执行null检查,如下面的代码

public class MainActivity extends AppCompatActivity {
private NavigationView navigationView;
private DrawerLayout drawerLayout;
private RecyclerView postlist;
private Toolbar mToolbar;
private ActionBarDrawerToggle actionBarDrawerToggle;
private FirebaseAuth mAuth;
private FirebaseUser FirebaseUser;
private DatabaseReference  UsersRef;
private CircleImageView NavProfileImage;
private ImageButton AddNewPostButton;
private TextView NavProfileUserName;
String currentUserID;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mAuth = FirebaseAuth.getInstance();
    final FirebaseUser mFirebaseUser = mAuth.getCurrentUser();
    if (mFirebaseUser != null) {
        currentUserID = mFirebaseUser.getUid();
    }




    mToolbar =(Toolbar) findViewById(R.id.main_page_toolbar);
    setSupportActionBar(mToolbar);
    getSupportActionBar().setTitle("Home");

    drawerLayout = (DrawerLayout) findViewById(R.id.drawable_layout);
   actionBarDrawerToggle =  new ActionBarDrawerToggle(MainActivity.this,drawerLayout,R.string.drawer_open, R.string.drawer_close);
    navigationView = (NavigationView)findViewById(R.id.navigation_view);
   AddNewPostButton = (ImageButton)findViewById(R.id.add_new_post_button);

    drawerLayout.addDrawerListener(actionBarDrawerToggle);
   actionBarDrawerToggle.syncState();
   getSupportActionBar().setDisplayHomeAsUpEnabled(true);


    View navView = navigationView.inflateHeaderView(R.layout.nav_header);
    NavProfileImage = (CircleImageView)navView.findViewById(R.id.nav_profile_image);
    NavProfileUserName = (TextView) navView.findViewById(R.id.nav_user_full_name);

    UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
      // replace below code
     if (mFirebaseUser != null) {

    UsersRef.child(currentUserID).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot)
        {
            if(dataSnapshot.exists())
            {   if (dataSnapshot.hasChild("fullname")){
                String fullname = dataSnapshot.child("fullname").getValue().toString();
                NavProfileUserName.setText(fullname);
            }if (dataSnapshot.hasChild("profileimage")) {
                String image = dataSnapshot.child("profileimage").getValue().toString();
                Picasso.with(MainActivity.this).load(image).placeholder(R.drawable.profile).into(NavProfileImage);

            }else {
                Toast.makeText(MainActivity.this, "Profile name do not exists...", Toast.LENGTH_SHORT).show();
            }




            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

    }else{
     sendUserToLoginActivity();
    }

    navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item)
        { UserMenuSelector(item);

            return false;
        }
    });
    AddNewPostButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            SendUserToPostActivity();

        }
    });
}

private void SendUserToPostActivity() {
    Intent addNewPostIntent = new Intent (MainActivity.this,PostActivity.class);
    startActivity(addNewPostIntent);
}

@Override
protected void onStart() {
    super.onStart();
    FirebaseUser currentUser = mAuth.getCurrentUser();
    if (currentUser == null)
    {
        sendUserToLoginActivity();
    }else{
        CheckUserExistance();
    }
}

private void CheckUserExistance()
{
    final String current_user_id = mAuth.getCurrentUser().getUid();
      UsersRef.addValueEventListener(new ValueEventListener() {
          @Override
          public void onDataChange(DataSnapshot dataSnapshot) {
              if (!dataSnapshot.hasChild(current_user_id)){
                  sendUserToSetupActivity();
              }
          }

          @Override
          public void onCancelled(DatabaseError databaseError) {

          }
      });
}

private void sendUserToSetupActivity() {
    Intent setupIntent = new Intent(MainActivity.this, SetupActivity.class);
    setupIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(setupIntent);
    finish();

}

private void sendUserToLoginActivity()
{
    Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
     loginIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
     startActivity(loginIntent);
     finish();

}

OR ,您也可以在此处直接检查

 if (mFirebaseUser != null) {
        currentUserID = mFirebaseUser.getUid();
    }else{
        sendUserToLoginActivity();
    }

答案 3 :(得分:0)

您之所以得到java.lang.NullPointerException: Can't pass null for argument 'pathString' in child(),是因为您在注销用户时没有将其发送到登录活动,这就是此错误的原因。解决此问题的最简单方法是使用侦听器。假设您有两个活动,LoginActivityMainActivity。可以在LoginActivity中创建的侦听器应如下所示:

FirebaseAuth.AuthStateListener authStateListener = new FirebaseAuth.AuthStateListener() {
    @Override
    public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
        FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
        if (firebaseUser != null) {
            Intent intent = new Intent(LoginActivity.this, MainActivity.class);
            startActivity(intent);
            finish();
        }
    }
};

这基本上意味着,如果用户已登录,则跳过LoginActivity并转到MainActivity

实例化FirebaseAuth对象:

FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();

然后开始监听onStart()方法中的更改,如下所示:

@Override
protected void onStart() {
    super.onStart();
    firebaseAuth.addAuthStateListener(authStateListener);
}

MainActivity中,您应该执行相同的操作:

FirebaseAuth.AuthStateListener authStateListener = new FirebaseAuth.AuthStateListener() {
    @Override
    public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
        FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
        if (firebaseUser == null) {
            Intent intent = new Intent(MainActivity.this, LoginActivity.class);
            startActivity(intent);
        }
    }
};

这基本上意味着,如果用户未登录,则跳过MainActivity并转到LoginActivity。在此活动中,您应该执行与LoginActivity中相同的操作,应该开始侦听onStart()中的更改。

这样,您将再也不会收到这样的错误。