my app crashes all the time, when I want to access a specific fragment. The error is:
FATAL EXCEPTION: main Process: com.akstudios.kindergarten, PID: 15680 java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager)' on a null object reference at com.akstudios.kindergarten.GroupbookKrippeFragment.setRecyclerView(GroupbookKrippeFragment.java:56)
I saw a lot of people had similar problems in the past, but no ideas or suggestions helped me to fix mine.
I tried to get the context with getContext(), onAttach(), GroupbookKrippeFragment.this.getContext() and some other ways.
UPDATE START (12.11.22)
I as able to narrow down the problem a bit more. The app is stable and working until I made the following change:
1.) For updating my tableList with recyclerview entries coming from my database, I encapsulate the following code to a new method within the GroupbookKrippeFragment.java:
public void setRecyclerView(List<ChildrenTable> childrenTableList) {
recycler_view.setLayoutManager(new LinearLayoutManager(getContext()));
childAdapter = new ChildAdapter(getContext(), childrenTableList);
// childAdapter = new ChildAdapter(getContext());
recycler_view.setAdapter(childAdapter);
}
2.) I called this method in my DatabaseHelper.java class on the onPostExecute() AsyncTask of AllChildren:
public class DatabaseHelper {
Context context;
GroupbookKrippeFragment groupbookKrippeFragment = new GroupbookKrippeFragment();
public DatabaseHelper(Context context) {
this.context = context;
}
public static DatabaseHelper getInstance(Context context) {
return new DatabaseHelper(context);
}
// Insert Data
// TODO: Add all columns as Input parameter for Database
public void addNewChild(
String child_name, String child_surname, String child_birthday,
String child_birthday_location, String child_confession, String child_nationality) {
class NewChild extends AsyncTask<Void, Void, ChildrenTable> {
@Override
protected ChildrenTable doInBackground(Void... voids) {
ChildrenTable childrenTable = new ChildrenTable();
// TODO: Link all columns for Database
childrenTable.setChild_name(child_name);
childrenTable.setChild_surname(child_surname);
childrenTable.setChild_birthday(child_birthday);
childrenTable.setChild_birthday_location(child_birthday_location);
childrenTable.setChild_confession(child_confession);
childrenTable.setChild_nationality(child_nationality);
DatabaseClient.getInstance(context)
.getChildrenDatabase()
.childrenDAO()
.insertData(childrenTable);
return childrenTable;
}
@Override
protected void onPostExecute(ChildrenTable childrenTable) {
super.onPostExecute(childrenTable);
if (childrenTable != null) {
Toast.makeText(
context,
childrenTable.getChild_name() + "\n" +
childrenTable.getChild_surname(), Toast.LENGTH_SHORT).show();
}
}
}
NewChild newChild = new NewChild();
newChild.execute();
}
// Show all data from ChildrenTable
public void getAllChildrenData() {
class AllChildren extends AsyncTask<Void, Void, List<ChildrenTable>> {
@Override
protected List<ChildrenTable> doInBackground(Void... voids) {
List<ChildrenTable> list = DatabaseClient.getInstance(context)
.getChildrenDatabase()
.childrenDAO()
.selectAll();
return list;
}
@Override
protected void onPostExecute(List<ChildrenTable> childrenTable) {
super.onPostExecute(childrenTable);
if (childrenTable != null && childrenTable.size() > 0) {
groupbookKrippeFragment.setRecyclerView(childrenTable);
}
}
}
AllChildren allChildren = new AllChildren();
allChildren.execute();
}
}
Whenever I comment out this method call and move the lines from the method into onViewCreated of GroupbookKrippeFragment, the app is stable again, but the recyclerView data is not showing and updating with my database.
UPDATE END (12.11.22)
Thanks a lot for your help in advance - here are my files:
GroupbookKrippeFragment.java
public class GroupbookKrippeFragment extends Fragment {
Button addChildBtn;
RecyclerView recycler_view;
ChildAdapter childAdapter;
DatabaseHelper helper;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_groupbook_krippe, container, false);
addChildBtn = view.findViewById(R.id.btn_groupBook_krippe_1);
addChildBtn.setOnClickListener(view1 -> {
Intent intent = new Intent(GroupbookKrippeFragment.this.getActivity(), GroupbookAddChildFragment.class);
startActivity(intent);
});
recycler_view = view.findViewById(R.id.recycler_view);
helper = DatabaseHelper.getInstance(getContext());
helper.getAllChildrenData();
return view;
}
public void setRecyclerView(List<ChildrenTable> childrenTableList) {
recycler_view.setLayoutManager(new LinearLayoutManager(getContext()));
childAdapter = new ChildAdapter(getContext(), childrenTableList);
recycler_view.setAdapter(childAdapter);
}
}
GroupbookFragment.java
public class GroupbookFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_groupbook, container, false);
// Tab layout initialization
TabLayout tabLayout = view.findViewById(R.id.tabLayout);
ViewPager2 viewPager = view.findViewById(R.id.viewPager_groupBook);
GroupbookAdapter adapterGroupBook = new GroupbookAdapter(getChildFragmentManager(), getLifecycle());
viewPager.setAdapter(adapterGroupBook);
// set 3 Tab titles
tabLayout.addTab(tabLayout.newTab().setText("Krippe"));
tabLayout.addTab(tabLayout.newTab().setText("Hafen"));
tabLayout.addTab(tabLayout.newTab().setText("Kindergarten"));
tabLayout.addOnTabSelectedListener(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) {
}
});
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});
return view;
}
}
Your
GroupbookKrippeFragmentowns aDatabaseHelper. YourDatabaseHelperowns another instance ofGroupbookKrippeFragmentthat is not involved in a fragment transaction and hence its lifecycle methods such asonCreateView()are not invoked, andrecycler_viewremains null in that instance.Rather than
DatabaseHelperinstantiating anew GroupbookKrippeFragment, you could e.g. pass in a reference to the owning fragment as a constructor argument, store it in a field, and callsetRecyclerView()on it later.It's not a perfect design but helps you one step forward in your development journey.