My app crash when:
- HomeActivity started
- Navigate to CategoryActivity or Open a DialogFragment that share the same recyclerview viewholder
- Navigate back to HomeActivity, tap on a ImageView that have setDrawable
- App crash
Hereby is the crash code
10-31 07:45:52.811 25005-25005/com.studio.douka E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.studio.douka, PID: 25005
java.lang.NullPointerException
at
android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:374)
at com.studio.douka.PostHolder.setLikeStatus(PostHolder.java:163)
at
com.studio.douka.PostDialogFragment$3.onDataChange(PostDialogFragment.java:110)
at com.google.android.gms.internal.zzaie.zza(Unknown Source)
at com.google.android.gms.internal.zzaje.zzcta(Unknown Source)
at com.google.android.gms.internal.zzajh$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Hereby is the codes that make the app crash
PostHolder.java
public class PostHolder extends RecyclerView.ViewHolder {
private static final String TAG = PostHolder.class.getSimpleName();
public TextView postTitle;
public ImageView postImage;
public TextView postLike;
public TextView postComment;
public ImageView gifImage;
public ImageView BtnPostMenu;
private static final int POST_TEXT_MAX_LINES = 6;
public ValueEventListener mLikeListener;
public ValueEventListener mCommentListener;
public DatabaseReference mPostRef;
public ValueEventListener mPostListener;
private final ImageView mLikeIcon;
private PostClickListener mListener;
public enum LikeStatus {LIKED, NOT_LIKED}
private String authorUID;
private String photoURL;
private String postKey;
private String currentStorageRef;
private String postText;
public PostHolder(View itemView) {
super(itemView);
postTitle = (TextView) itemView.findViewById(R.id.item_title);
postImage = (ImageView) itemView.findViewById(R.id.item_icon);
postLike = (TextView) itemView.findViewById(R.id.item_like);
postComment = (TextView) itemView.findViewById(R.id.item_comment);
mLikeIcon = (ImageView) itemView.findViewById(R.id.post_like_icon);
BtnPostMenu = (ImageView) itemView.findViewById(R.id.post_menu_button);
gifImage = (ImageView) itemView.findViewById(R.id.gif_image);
itemView.findViewById(R.id.post_comment_icon).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.showComments();
}
});
mLikeIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.toggleLike();
}
});
BtnPostMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPopup(v);
}
});
}
public void setPhoto(String url, int width, int height, String isAnimated) {
GlideUtil.loadImage(url, postImage, width, height, isAnimated, gifImage);
}
public void getAuthor(String author) {
if (author != null) {
authorUID = author;
}
}
public void getStorageRef(String storageRef) {
if (storageRef != null) {
currentStorageRef = storageRef;
}
}
public void getPhotoURL(String picURL) {
if (picURL != null) {
photoURL = picURL;
}
}
public void getKey(String key) {
if (key != null) {
postKey = key;
}
}
public void getText(String pText) {
if (pText != null) {
postText = pText;
}
}
public void setText(final String text) {
if (text == null || text.isEmpty()) {
postTitle.setVisibility(View.GONE);
return;
} else {
postTitle.setVisibility(View.VISIBLE);
postTitle.setText(text);
postTitle.setMaxLines(POST_TEXT_MAX_LINES);
postTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (postTitle.length() == POST_TEXT_MAX_LINES) {
postTitle.setMaxLines(Integer.MAX_VALUE);
} else {
postTitle.setMaxLines(POST_TEXT_MAX_LINES);
}
}
});
}
}
public void setNumLikes(long numLikes) {
String suffix = numLikes == 1 ? " like" : " likes";
postLike.setText(numLikes + suffix);
}
public void setNumComments(long numComments) {
String suffix = numComments == 1 ? " comment" : " comments";
postComment.setText(numComments + suffix);
}
public void setLikeStatus(LikeStatus status, Context context) {
mLikeIcon.setImageDrawable(ContextCompat.getDrawable(context,
status == LikeStatus.LIKED ? R.drawable.heart_full : R.drawable.heart_empty));
}
public void setPostClickListener(PostClickListener listener) {
mListener = listener;
}
public interface PostClickListener {
void showComments();
void toggleLike();
}
public void showPopup(final View v) {
final String currentUID = FirebaseUtil.getCurrentUserId();
if (authorUID.equals(currentUID)) {
PopupMenu popup = new PopupMenu(v.getContext(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.own_post_menu_popup, popup.getMenu());
popup.getMenu().findItem(R.id.action_edit).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
showChangeLangDialog(v);
return false;
}
});
popup.getMenu().findItem(R.id.action_delete).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageRef = storage.getReferenceFromUrl(photoURL);
storageRef.delete().addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Object o) {
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("posts/" + postKey, null);
childUpdates.put("comments/" + postKey, null);
childUpdates.put("likes/" + postKey, null);
childUpdates.put("userNotifications/" + currentUID + "/" + postKey, null);
childUpdates.put("people/" + currentUID + "/" + "posts/" + postKey, null);
childUpdates.put("postCategory/car/" + postKey, null);
childUpdates.put("postCategory/funny/" + postKey, null);
childUpdates.put("postCategory/gaming/" + postKey, null);
childUpdates.put("postCategory/girl/" + postKey, null);
FirebaseUtil.getBaseRef().updateChildren(childUpdates);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
// Uh-oh, an error occurred!
}
});
return false;
}
});
popup.show();
} else {
PopupMenu popup = new PopupMenu(v.getContext(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.post_menu_popup, popup.getMenu());
popup.getMenu().findItem(R.id.action_report).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(v.getContext(), "Reported,,,", Toast.LENGTH_SHORT).show();
return false;
}
});
popup.show();
}
}
public void showChangeLangDialog(View v) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(v.getContext());
LayoutInflater inflater = (LayoutInflater) v.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);;
final View dialogView = inflater.inflate(R.layout.custom_dialog, null);
dialogBuilder.setView(dialogView);
final EditText edt = (EditText) dialogView.findViewById(R.id.edit1);
edt.setText(postText);
dialogBuilder.setTitle("Custom dialog");
dialogBuilder.setMessage("Enter text below");
dialogBuilder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//do something with edt.getText().toString();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("text", edt.getText().toString());
FirebaseUtil.getPostsRef().child(postKey).updateChildren(childUpdates);
}
});
dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//pass
}
});
AlertDialog b = dialogBuilder.create();
b.show();
}
}
PostDialogFragment.java
public class PostDialogFragment extends DialogFragment {
private static final String TAG = MainActivity.class.getSimpleName();
private String postID = null;
private OnPostSelectedListener mListener;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter<PostHolder> mAdapter;
public PostDialogFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_post_dialog, container, false);
getDialog().setTitle("Post");
postID = getArguments().getString("postID");
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.postRecyclerView);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
mRecyclerView.setLayoutManager(linearLayoutManager);
final List<String> postPaths = new ArrayList<>();
postPaths.add(postID);
mAdapter = new FirebasePostQueryAdapter(postPaths,
new FirebasePostQueryAdapter.OnSetupViewListener() {
@Override
public void onSetupView(PostHolder holder, Post post, int position, String postKey) {
setupPost(holder, post, position, postKey);
}
});
mRecyclerView.setAdapter(mAdapter);
}
private void setupPost(final PostHolder postViewHolder, final Post post, final int position, final String inPostKey) {
postViewHolder.setPhoto(post.getFull_url(), post.getImageWidth(), post.getImageHeight(), post.getIsAnimated());
postViewHolder.setText(post.getText());
postViewHolder.getAuthor(post.getAuthor().getUid());
postViewHolder.getPhotoURL(post.getFull_url());
postViewHolder.getStorageRef(getString(R.string.google_storage_bucket));
postViewHolder.getText(post.getText());
final String postKey;
if (mAdapter instanceof FirebaseRecyclerAdapter) {
postKey = ((FirebaseRecyclerAdapter) mAdapter).getRef(position).getKey();
postViewHolder.getKey(((FirebaseRecyclerAdapter) mAdapter).getRef(position).getKey());
} else {
postKey = inPostKey;
}
ValueEventListener likeListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
postViewHolder.setNumLikes(dataSnapshot.getChildrenCount());
if (dataSnapshot.hasChild(FirebaseUtil.getCurrentUserId())) {
postViewHolder.setLikeStatus(PostHolder.LikeStatus.LIKED, getActivity());
} else {
postViewHolder.setLikeStatus(PostHolder.LikeStatus.NOT_LIKED, getActivity());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
FirebaseUtil.getLikesRef().child(postKey).addValueEventListener(likeListener);
postViewHolder.mLikeListener = likeListener;
ValueEventListener commentListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
postViewHolder.setNumComments(dataSnapshot.getChildrenCount());
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
FirebaseUtil.getCommentsRef().child(postKey).addValueEventListener(commentListener);
postViewHolder.mCommentListener = commentListener;
postViewHolder.setPostClickListener(new PostHolder.PostClickListener() {
@Override
public void showComments() {
Log.d(TAG, "Comment position: " + position);
mListener.onPostComment(postKey);
}
@Override
public void toggleLike() {
Log.d(TAG, "Like position: " + position);
mListener.onPostLike(postKey);
}
});
}
public interface OnPostSelectedListener {
void onPostComment(String postKey);
void onPostLike(String postKey);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnPostSelectedListener) {
mListener = (OnPostSelectedListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnPostSelectedListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
}
HomeActivity.java
public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, PostFragment.OnPostSelectedListener, PostDialogFragment.OnPostSelectedListener, UploadMethodDialogFragment.OnImageSelectedListener {
private AlertDialog userDialog;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
viewPager = (ViewPager) findViewById(R.id.viewPager);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
FeedsPagerAdapter adapter = new FeedsPagerAdapter(getSupportFragmentManager());
adapter.addFragment(PostFragment.newInstance(PostFragment.TYPE_NEW), "NEW");
adapter.addFragment(PostFragment.newInstance(PostFragment.TYPE_CATEGORY), "CATEGORY");
adapter.addFragment(PostFragment.newInstance(PostFragment.TYPE_NOTIFICATION), "NOTIFICATIONS");
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(0);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View header = navigationView.getHeaderView(0);
TextView navName = (TextView) header.findViewById(R.id.nav_header_name);
TextView navEmail = (TextView) header.findViewById(R.id.nav_header_email);
ImageView navProfilePicture = (ImageView) header.findViewById(R.id.nav_profile_picture);
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// Name, email address, and profile photo Url
String user_name = user.getDisplayName();
String user_email = user.getEmail();
Uri pictureURL = user.getPhotoUrl();
navName.setText("" + user_name);
navEmail.setText("" + user_email);
Glide
.with(getApplicationContext())
.load(pictureURL)
.into(navProfilePicture);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
viewPager.setCurrentItem(0);
} else if (id == R.id.nav_gallery) {
viewPager.setCurrentItem(1);
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
class FeedsPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public FeedsPagerAdapter(android.support.v4.app.FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
@Override
public void onPostComment(String postKey) {
if (postKey == null) {
showAlertDialog("无法连接",
"Key : " + postKey, false);
} else {
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
CommentFragment um = new CommentFragment();
Bundle args = new Bundle();
args.putString("postKey", postKey);
um.setArguments(args);
um.show(fm, "Comment");
}
}
@Override
public void onPostLike(final String postKey) {
final String userKey = FirebaseUtil.getCurrentUserId();
final DatabaseReference postLikesRef = FirebaseUtil.getLikesRef();
postLikesRef.child(postKey).child(userKey).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// User already liked this post, so we toggle like off.
postLikesRef.child(postKey).child(userKey).removeValue();
} else {
postLikesRef.child(postKey).child(userKey).setValue(ServerValue.TIMESTAMP);
}
}
@Override
public void onCancelled(DatabaseError firebaseError) {
}
});
}
@Override
public void onUpdateNotification(final String postKey) {
final String userKey = FirebaseUtil.getCurrentUserId();
final DatabaseReference notificationRef = FirebaseUtil.getUserNotificationsRef();
notificationRef.child(userKey).child(postKey).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
HashMap<String, Object> result = new HashMap<>();
result.put("status", false);
result.put("count", 0L);
notificationRef.child(userKey).child(postKey).updateChildren(result);
}
}
@Override
public void onCancelled(DatabaseError firebaseError) {
}
});
}
@Override
public void onPostOpenDialog(final String postKey) {
Bundle bundle = new Bundle();
bundle.putString("postID", postKey);
//set Fragment class Arguments
PostDialogFragment fragObj = new PostDialogFragment();
fragObj.setArguments(bundle);
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
fragObj.show(fm, "Post Fragment");
}
public void onPicSelected(String filePath) {
if(filePath!=null){
Bundle bundle = new Bundle();
bundle.putString("filePath", filePath);
//set Fragment class Arguments
UploadPictureDialogFragment fragObj = new UploadPictureDialogFragment();
fragObj.setArguments(bundle);
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
fragObj.show(fm, "上载图片");
}
}
public void userDetails(MenuItem item) {
// [START subscribe_topics]
FirebaseMessaging.getInstance().subscribeToTopic("6biC3YfNUiWpHqmasa4O74KPWwC2");
// [END subscribe_topics]
// Log and toast
String msg = "Subscribed to news topic";
Log.d("Subscribe", msg);
Toast.makeText(HomeActivity.this, msg, Toast.LENGTH_SHORT).show();
}
public void upload_method(MenuItem item) {
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
UploadMethodDialogFragment um = new UploadMethodDialogFragment();
um.show(fm, "Upload Method");
}
private void showAlertDialog(String title, String body, Boolean status) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(title).setMessage(body).setNeutralButton("好的", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
try {
userDialog.dismiss();
} catch (Exception e) {
//
}
}
});
userDialog = builder.create();
userDialog.show();
}
@Override
public void onBackPressed() {
viewPager.setCurrentItem(0);
}
}
I uploaded gif picture as well for better understanding