Ошибка передачи данных bundle
В моём RecyclerView есть item по нажатию на который у меня открывается Fragment в нём есть TextView, мне нужно что бы он отображал данные взятые из bundle, в свою очередь bundle будет брать данные из БД. Но при открытии фрагмента приложение крашиться с ошибкой
2021-03-27 14:19:33.907 20869-20869/com.example.des E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.des, PID: 20869
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.BaseBundle.getString(java.lang.String)' on a null object reference
at com.example.des.Menu.Tasks.FragmentTasksBlanc.onViewCreated(FragmentTasksBlanc.java:44)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:892)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
Мой onBindViewHolder из Adapter
@Override
public void onBindViewHolder(@NonNull AdapterTasks.ViewHolder holder, int position) {
ItemTasks currentItem = itemTasks.get(position);
holder.tv_item_tasks.setText(currentItem.getTitleTasks());
holder.cv_item_tasks.setOnClickListener(v ->
{
FragmentTasksBlanc fragment = new FragmentTasksBlanc();
itemClickTasks.onItemClickTasks(holder.getAdapterPosition());
Bundle bundle = new Bundle();
bundle.putString("TitleTasks", currentItem.getTitleTasks());
fragment.setArguments(bundle);
});
Glide.with(context)
.load(currentItem.getImageTasks())
.into(holder.iv_item_tasks);
}
Fragment который крашит приложение
public class FragmentTasksBlanc extends Fragment {
TextView tv_tasks_title;
public static FragmentTasksBlanc newInstance() {
return new FragmentTasksBlanc();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tasks_blanc, container, false);
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
tv_tasks_title = requireView().findViewById(R.id.tv_tasks_title);
Bundle bundle = getArguments();
tv_tasks_title.setText(bundle.getString("TitleTasks"));
}
}
Создание фрагмента
private void replaceFragment(@NonNull Fragment fragment) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction tr = fm.beginTransaction();
tr.replace(R.id.content, fragment);
tr.commitAllowingStateLoss();
curFragment = fragment;
}
Переход по нажатию с помощью interface, находиться в MainActivity
@Override
public void onItemClickTasks(int position) {this.showFragment(FragmentTasksBlanc.newInstance());}
Сам interface
public interface ItemClickTasks {
void onItemClickTasks(int position);
}
Ответы (3 шт):
Поменяйте код фрагмента
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view;
view = inflater.inflate(R.layout.fragment_tasks_blanc, container, false);
tv_tasks_title = (TextView) view.findViewById(R.id.tv_tasks_title);
Bundle bundle = getArguments();
tv_tasks_title.setText(bundle.getString("TitleTasks"));
return view;
}
Проблема заключается в том что setArguments нужно применять на тот Fragment на который переходишь, но так как у меня replace Fragment находиться в MainActivity, при переходе bundle оставался пустым. Решение оказалось простым хотя не знаю насколько правильным, т.к. Fragment в MainActivity пришлось сделать static
Было
public Fragment curFragment;
Стало
public static Fragment curFragment;
И в Adapter указывал таким образом
MainActivity.curFragment.setArguments(bundle);
Нужно устанавливать аргументы именно у того экземпляра класса FragmentTasksBlanc, который вы потом показываете с помощью FragmentTransaction. Для этого вы можете например поменять код в интерфейсе на следующий, чтобы в метод интерфейса передавалась нужная вам строка:
@Override
public void onItemClickTasks(String titleTasks) {
FragmentTasksBlanc fragment = new FragmentTasksBlanc();
Bundle bundle = new Bundle();
bundle.putString("TitleTasks", titleTasks);
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss();
}
Тогда код в onBindViewHolder поменяется на следующий. Здесь мы просто вызываем метод onItemClickTasks интерфейса и передаем туда строку, содержащую заголовок.
@Override
public void onBindViewHolder(@NonNull AdapterTasks.ViewHolder holder, int position) {
ItemTasks currentItem = itemTasks.get(position);
holder.tv_item_tasks.setText(currentItem.getTitleTasks());
holder.cv_item_tasks.setOnClickListener(v ->
{
itemClickTasks.onItemClickTasks(currentItem.getTitleTasks());
});
Glide.with(context)
.load(currentItem.getImageTasks())
.into(holder.iv_item_tasks);
}