I have a button placed inside a layout frag_contacts.xml that is intended for a fragment which is FragmentContacts.java . There is also row layout for the recyclerview which is items_contacts.xml . The button allows a user to save stuff after they are done picking recyclerview items. The app works without any errors on android Nougat .
However When I run the app on android 9 it crushes giving exception java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference.
The line throwing exceptions is the one below
buttonCreateGroup.setOnClickListener(this);
the error message
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.ex_contactapp, PID: 3931
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.example.ex_contactapp.fragments.FragmentContacts.onCreateView(FragmentContacts.java:99)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2439)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2243)
at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:654)
at androidx.fragment.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:146)
at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
at android.view.View.measure(View.java:25056)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7745)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
at android.view.View.measure(View.java:25056)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7745)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
at android.view.View.measure(View.java:25056)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7745)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
at android.view.View.measure(View.java:25056)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7745)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:25056)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7745)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
at android.view.View.measure(View.java:25056)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7745)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:1051)
at android.view.View.measure(View.java:25056)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3382)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2104)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2403)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1964)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8721)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:988)
at android.view.Choreographer.doCallbacks(Choreographer.java:765)
at android.view.Choreographer.doFrame(Choreographer.java:700)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:967)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7285)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
layout for fragment - frag_contacts.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark">
<GridLayout
android:layout_width="wrap_content"
android:layout_height="100dp">
<EditText
android:id="@+id/group_name"
android:layout_width="263dp"
android:layout_height="70dp"/>
<Button
android:id="@+id/buttonCreateGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/create_group"/>
</GridLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_contacts"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
Row layout -> items_contacts.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:layout_margin="10dp"
android:weightSum="10">
<Button
android:layout_gravity="center"
android:background="@drawable/ic_person"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="32dp"/>
<LinearLayout
android:padding="10dp"
android:layout_width="0dp"
android:layout_weight="8"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/contact_name"
android:text="name"
android:textSize="20sp"
android:textColor="@android:color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/contact_number"
android:text="number"
android:textSize="16sp"
android:textColor="@android:color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<CheckBox
android:id="@+id/contact_checkbox"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_height="32dp"
android:layout_weight="1"/>
</LinearLayout>
Recycler View Adapter class -ContactsRvAdapter.java
public class ContactsRvAdapter extends RecyclerView.Adapter<ContactsRvAdapter.ViewHolder> {
private Context mContext;
private LayoutInflater inflater;
private List<ModelContacts> mlistContacts;
private CheckedStatusListener mcheckedStatusListener;
public interface CheckedStatusListener{
//String firstName, String lastName, String middleName, @NonNull String phoneNumber,@NonNull int groupid
void onItemChecked(String name, String phonenumber);
void onItemUnchecked(String name, String phonenumber);
}
public ContactsRvAdapter(Context context, List<ModelContacts> listContacts,CheckedStatusListener checkedStatusListener){
mlistContacts = listContacts;
mContext = context;
mcheckedStatusListener = checkedStatusListener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.items_contacts,parent,false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
final TextView contact_name,contact_number;
final CheckBox contact_checkbox;
contact_name = holder.contact_name;
contact_number = holder.contact_number;
contact_name.setText(mlistContacts.get(position).getName());
contact_number.setText(mlistContacts.get(position).getNumber());
contact_checkbox = holder.contactSelectedCheckBox;
contact_checkbox.setOnClickListener(v -> {
if (contact_checkbox.isChecked()){
mcheckedStatusListener.onItemChecked(mlistContacts.get(position).getName(),mlistContacts.get(position).getNumber());
}else{
mcheckedStatusListener.onItemUnchecked(mlistContacts.get(position).getName(),mlistContacts.get(position).getNumber());
}
});
}
@Override
public int getItemCount() {
return mlistContacts.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView contact_name,contact_number;
CheckBox contactSelectedCheckBox;
public ViewHolder(View itemView){
super(itemView);
contact_name = itemView.findViewById(R.id.contact_name);
contact_number = itemView.findViewById(R.id.contact_number);
contactSelectedCheckBox = itemView.findViewById(R.id.contact_checkbox);
}
}
}
Fragment class - FragmentContacts.java
public class FragmentContacts extends Fragment implements ContactsRvAdapter.CheckedStatusListener, View.OnClickListener{
private View v;
private RecyclerView recyclerView;
private List<ModelContactsBuffer> currentSelectedContacts = new ArrayList<>();
ContactsRvAdapter adapter;
private EditText editTextGroupName;
private ContactGroupViewModel contactGroupViewModel;
private ModelContactsBuffer modelContactsBuffer;
private GroupListViewModel groupListViewModel;
public FragmentContacts() {
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
v = inflater.inflate(R.layout.frag_contacts,container,false);
recyclerView = v.findViewById(R.id.rv_contacts);
editTextGroupName = v.findViewById(R.id.group_name);
Button buttonCreateGroup = v.findViewById(R.id.buttonCreateGroup);
buttonCreateGroup.setOnClickListener(this);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
RecyclerView.LayoutManager layoutManager= linearLayoutManager;
recyclerView.setLayoutManager(layoutManager);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M &&
ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.READ_CONTACTS},1);
}else {
adapter = new ContactsRvAdapter(getContext(), getContacts(),this);
recyclerView.setItemViewCacheSize(getContacts().size());
recyclerView.setAdapter(adapter);
// adapter.notifyDataSetChanged();
}
contactGroupViewModel = ViewModelProviders.of(this, new ContactGroupViewModel.Factory(Objects.requireNonNull(getActivity()).getApplicationContext())).get(ContactGroupViewModel.class);
groupListViewModel = ViewModelProviders.of(this,new GroupListViewModel.Factory(getActivity().getApplicationContext())).get(GroupListViewModel.class);
return v;
}
@Override
public void onClick(View v) {
Log.i("editTextGroupNamelength", String.valueOf(editTextGroupName.getText().toString().length()));
if (editTextGroupName.getText().toString().length() > 2) {
if(currentSelectedContacts.size() > 4){
contactGroupViewModel.createGroup(editTextGroupName.getText().toString(),String.valueOf(currentSelectedContacts.size()));
Integer groupId = contactGroupViewModel.readGroupId(editTextGroupName.getText().toString());
insertGrouplist(groupId);
//clearFields();
}else{
new AlertDialog.Builder(Objects.requireNonNull(this.getActivity()))
.setIcon(R.drawable.ic_error)
.setTitle("Insufficient group members")
.setMessage("A group should have at least 5 members")
.setNeutralButton("Ok",null)
.show();
}
}else{
new AlertDialog.Builder(Objects.requireNonNull(this.getActivity()))
.setIcon(R.drawable.ic_error)
.setTitle("Group name is too short")
.setMessage("A group should have atleast be 3 characters long")
.setNeutralButton("Ok",null)
.show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(requestCode == 1){
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
//now permission is granted call function again
adapter = new ContactsRvAdapter(getContext(), getContacts(),this);
recyclerView.setItemViewCacheSize(getContacts().size());
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
}
private List<ModelContacts> getContacts(){
List<ModelContacts> list = new ArrayList<>();
try{
String[] PROJECTION = new String[] {
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Photo.CONTACT_ID };
String selectionFields = ""+ ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and " + ContactsContract.CommonDataKinds.Phone.TYPE +"=" + ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;
String[] selectionArgs = new String[]{"com.google"};
Cursor cursor = getContext().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
PROJECTION,selectionFields,null,ContactsContract.Contacts.DISPLAY_NAME + " ASC");
cursor.moveToFirst();
while(cursor.moveToNext()){
list.add(new ModelContacts(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)),
cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)),
cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))));
}
}catch (Exception e){
Toast.makeText(getContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
}
return list;
}
@Override
public void onItemChecked(String name, String phonenumber) {
String firstName = " ";
String lastName = " ";
if(name.split("\\w+").length>1){
lastName = name.substring(name.lastIndexOf(" ")+1);
firstName = name.substring(0,name.lastIndexOf(' '));
}else{
firstName = name;
lastName = " ";
}
modelContactsBuffer = new ModelContactsBuffer(firstName,lastName,phonenumber);
currentSelectedContacts.add(modelContactsBuffer);
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onItemUnchecked(String name, String phonenumber) {
String firstName = " ";
String lastName = " ";
if(name.split("\\w+").length>1){
lastName = name.substring(name.lastIndexOf(" ")+1);
firstName = name.substring(0,name.lastIndexOf(' '));
}else{
firstName = name;
lastName = " ";
}
currentSelectedContacts.removeIf( currentSelectedContact -> currentSelectedContact.getPhoneNumber().equals(phonenumber));
}
public void insertGrouplist(int groupId){
for (ModelContactsBuffer currentSelectedContact : currentSelectedContacts) {
groupListViewModel.createGroupList(currentSelectedContact.getFirstName(), currentSelectedContact.getLastName(), " ", currentSelectedContact.getPhoneNumber(), groupId);
}
clearFields();
}
}
- I commented the line throwing an exception and the app runs pretty well. Hence the problem is from
buttonCreateGroup.setOnClickListener(this);
- I have tried many solutions here in stack overflow which didnt work.
- I have checked the id of the button and it is correct
- I don't think it is possible initializing the onclicklistener inside ContactsRvAdapter because its not even in the row layout. It is in the other layout wwhich is intended for the fragment
- I tried passing the normal new OnViewClicklistener to the button instead of passing the whole activity but nothong changed. Still getting an error
- I later on moved the clicklistener call from
public View onCreateView()
topublic void onViewCreated()
but there was no change. I am stil getting the same error. - I tried removing
@RequiresApi(api = Build.VERSION_CODES.N)
Nothing changed
Kindly note I am not a professional on android. I added some things like @RequiresApi(api = Build.VERSION_CODES.N)
because android lint would show an error and that was the only way I could deal with it at that time. I apprectiate any help offered on solving this