该应用程序的想法是使用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;
}