该应用程序的想法是使用Firebase在地图上查看在线用户的位置。

我一直遵循在线YouTube tutorial来实现我的想法。

该应用程序显示在在线用户电子邮件的RecyclerView中。

单击它们后,它将在地图上显示其位置。

问题是,当我单击时,它因以下异常而崩溃:


  java.lang.NullPointerException:尝试调用接口方法
  '无效
  com.example.ahmad.easytrack2.ItemClickListener.onClick(android.view.View,
  int)'在空对象引用上
  在com.example.ahmad.easytrack2.ListOnlineViewHolder.onClick


我不知道为什么,但是它说对象为空。

ListOnline活动:

public class ListOnline extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
     LocationListener {

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

//view
RecyclerView listOnline;
RecyclerView.LayoutManager layoutManager;

//location
private static final int MY_PERMISSION_REQUEST_CODE = 7171;
private static final int PLAY_SERVICES_RES_REQUEST = 7172;
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;

private static int UPDATE_INTERVAL = 5000;
private static int FASTEST_INTERVAL = 3000;
private static int DISTANCE = 10;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_online);

    //init views
    listOnline = (RecyclerView)findViewById(R.id.listOnline);
    listOnline.setHasFixedSize(true);
    layoutManager = new LinearLayoutManager(this);
    listOnline.setLayoutManager(layoutManager);


    //Set toolbar and layout / join menu
    Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
    toolbar.setTitle("Presence system");
    setSupportActionBar(toolbar);

    //firebase
    locations = FirebaseDatabase.getInstance().getReference("Locations");
    onlineRef = FirebaseDatabase.getInstance().getReference().child(".info/connected");
    counterRef = FirebaseDatabase.getInstance().getReference("lastOnline");
    currentUserRef = FirebaseDatabase.getInstance().getReference("lastOnline")
                        .child(FirebaseAuth.getInstance().getCurrentUser().getUid());
    if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
        ActivityCompat.requestPermissions(this,new String[]{
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION
        },MY_PERMISSION_REQUEST_CODE);
    }
    else
    {
        if(checkPlayServices())
        {
            buildGoogleApiClient();
            createLocationRequest();
            displayLocation();
        }
    }

    setupSystem();

    updateList();

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode)
    {
        case MY_PERMISSION_REQUEST_CODE:
        {
            if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                if(checkPlayServices()){
                    buildGoogleApiClient();
                    createLocationRequest();
                    displayLocation();
                }
            }
        }
        break;
    }
}

private void displayLocation() {
    if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
        return;
    }
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    if(mLastLocation != null){
        //update to firebase
        locations.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                .setValue(new Tracking(FirebaseAuth.getInstance().getCurrentUser().getEmail(),
                        FirebaseAuth.getInstance().getCurrentUser().getUid(),
                        String.valueOf(mLastLocation.getLatitude()),
                        String.valueOf(mLastLocation.getLongitude())));

    }
    else
    {
        //Toast.makeText(this,"Couldn't get the location!",Toast.LENGTH_SHORT).show();
        Log.d("TEST", "Couldn't get the location");
    }
}

private void startLocationUpdates() {
    if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
      return;
    }
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,this);
}

private void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL);
    mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
    mLocationRequest.setSmallestDisplacement(DISTANCE);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

}

private void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API).build();
    mGoogleApiClient.connect();
}

private boolean checkPlayServices() {
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if(resultCode != ConnectionResult.SUCCESS){
        if(GooglePlayServicesUtil.isUserRecoverableError(resultCode)){
            GooglePlayServicesUtil.getErrorDialog(resultCode,this,PLAY_SERVICES_RES_REQUEST).show();
        }
        else{
            Toast.makeText(this,"This device is not supported",Toast.LENGTH_SHORT).show();
            finish();
        }
        return false;
    }
    return true;
}

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

            //implemnting itemclick inside recyclerview
            viewHolder.itemClickListener = new ItemClickListener() {
                @Override
                public void onClick(View view, int position) {
                    if(!model.getEmail().equals(FirebaseAuth.getInstance().getCurrentUser().getEmail())){
                         Intent map = new Intent(ListOnline.this,MapTracking.class);
                         map.putExtra("email",model.getEmail());
                         map.putExtra("lat",mLastLocation.getLatitude());
                         map.putExtra("lng",mLastLocation.getLongitude());
                         startActivity(map);
                    }
                }
            };
        }
        @Override
        public void onBindViewHolder(ListOnlineViewHolder viewHolder, int position) {
            viewHolder.setItemClickListener(viewHolder.itemClickListener);
        }
    };
    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();
                counterRef.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                        .setValue(new User(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 inflater = getMenuInflater();
    inflater.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(new User(FirebaseAuth.getInstance().getCurrentUser().getEmail(),"Online"));
            break;
        case R.id.action_logout:
            currentUserRef.removeValue();
            break;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onLocationChanged(Location location) {
    mLastLocation = location;
    displayLocation();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    displayLocation();
    startLocationUpdates();
}

@Override
protected void onStart() {
    super.onStart();
    if(mGoogleApiClient != null){
        mGoogleApiClient.connect();
    }
}

@Override
protected void onStop() {
    super.onStop();
    if(mGoogleApiClient != null){
        mGoogleApiClient.disconnect();
    }
}

@Override
protected void onResume() {
    super.onResume();
    checkPlayServices();
}

@Override
public void onConnectionSuspended(int i) {
    mGoogleApiClient.connect();
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}}


ListOnlineViewHolder类:

public class ListOnlineViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txtEmail;

ItemClickListener itemClickListener;

public ListOnlineViewHolder(View itemView) {

    super(itemView);
    txtEmail = (TextView) itemView.findViewById(R.id.txt_email);
    itemView.setOnClickListener(this);
}

public void setItemClickListener(ItemClickListener itemClickListener) {
    this.itemClickListener = itemClickListener;
}

@Override
public void onClick(View view) {
    itemClickListener.onClick(view, getAdapterPosition());
}}


MapTracking活动:

public class MapTracking extends AppCompatActivity implements OnMapReadyCallback {

private GoogleMap mMap;

private String email;

DatabaseReference locations;
Double lat,lng;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map_tracking);

    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map1);
    mapFragment.getMapAsync(this);

    //refrence to firebase locations
    locations = FirebaseDatabase.getInstance().getReference("Locations");

    //get intent data
    if(getIntent() != null){
        email = getIntent().getStringExtra("email");
        lat = getIntent().getDoubleExtra("lat",0);
        lng = getIntent().getDoubleExtra("lng",0);
    }
    if(!TextUtils.isEmpty(email)){
        loadLocationForThisUser(email);
    }


}

private void loadLocationForThisUser(String email) {
    Query user_location = locations.orderByChild("email").equalTo(email);

    user_location.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot postSnapshot:dataSnapshot.getChildren()){

                Tracking tracking = postSnapshot.getValue(Tracking.class);

                //Marker for friend location
                LatLng freindLocation = new LatLng(Double.parseDouble(tracking.getLat()),
                        Double.parseDouble(tracking.getLng()));

                //creating location from user coordinates
                Location currentUser = new Location("");
                currentUser.setLatitude(lat);
                currentUser.setLongitude(lng);

                //creating location from friend location
                Location freind = new Location("");
                freind.setLongitude(Double.parseDouble(tracking.getLng()));
                freind.setLatitude(Double.parseDouble(tracking.getLat()));

                //creating function to calculate the distance between two users
                distance(currentUser,freind);

                mMap.addMarker(new MarkerOptions()
                        .position(freindLocation)
                        .title(tracking.getEmail())
                        .snippet("Distance "+new DecimalFormat("#.#").format(distance(currentUser,freind)))
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat,lng),12.0f));

            }
            //create marker for current user
            LatLng current = new LatLng(lat,lng);
            mMap.addMarker(new MarkerOptions().position(current).title(FirebaseAuth.getInstance().getCurrentUser().getEmail()));
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

private double distance(Location currentUser, Location freind) {
    Double theta = currentUser.getLongitude() - freind.getLongitude();
    Double dist = Math.sin(deg2rad(currentUser.getLatitude()))
            * Math.sin(deg2rad((freind.getLatitude())))
            * Math.cos(deg2rad(currentUser.getLatitude()))
            * Math.cos(deg2rad(freind.getLatitude()))
            * Math.cos(deg2rad(theta));
    dist = Math.acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;
    return (dist);
}

private Double rad2deg(Double rad) {
    return (rad * 180.0 / Math.PI);
}

private double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}

@Override
public void onMapReady(GoogleMap googleMap) {

}}


ItemClickListener接口:

public interface ItemClickListener {
void onClick(View view,int position);}


为什么收到NullPointerException

最佳答案

缺少适配器代码,但问题是您从未在ItemClickListener itemClickListener中初始化ListOnlineViewHolder

onCreateViewHolder (ViewGroup parent, int viewType)中实例化它并在其构造函数中进行设置时,您可能希望将其作为参数传递。

像这样:

public ListOnlineViewHolder(View itemView, ItemClickListener itemClickListener) {

    super(itemView);
    txtEmail = (TextView) itemView.findViewById(R.id.txt_email);
    itemView.setOnClickListener(this);
    this.itemClickListener = itemClickListener;
}

09-05 04:17