Есть следующая проблема- На мобильном приложении есть 1 активити и 2 фрагмента.
Первый фрагмент- главное меню. В нём есть список уровней в виде различных ImageView и навешанных на них слушателей. По клику на уровень, открывается второй фрагмент со списком заданий в этом уровне. Список заданий отображается в ViewPager'e . В качестве адаптера использую собственную имплементацию FragmentStatePagerAdapter . Но вот в чем проблема- если часто переходить со второго фрагмента на первый и обратно посредством нажатия кнопки "Назад" (или onBackPressed(), это не имеет значения), то приложение крашится с ошибкой
java.lang.IllegalArgumentException: No view found for id 0x7f0e00e0 (ru.timuruktus.febree:id/tasksFragmentViewPager) for fragment TaskFragment{ab8ac48 #6 id=0x7f0e00e0}
Что уже только не перепробовал- и пытался id присвоить ViewPager'у и чистил проект и изменял адаптер так и сяк, и уже кучу всего, что я уже не помню. Ничего не помогает. Собственно, вот все необходимые вставки кода:
StepsFragment.java (Первый фрагмент)
public class StepsFragment extends Fragment implements BaseStepsFragment{
public View rootView;
private ImageView[][] taskIcons = new ImageView[BLOCK_COUNT][BLOCK_STEPS_COUNT];
private TextView[][] taskNames = new TextView[BLOCK_COUNT][BLOCK_STEPS_COUNT];
private Context context;
private BaseStepsPresenter presenter;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
rootView =
inflater.inflate(R.layout.steps_fragment, container, false);
Log.d("mytag", "Creating new fragment");
context = rootView.getContext();
presenter = new StepsPresenter(this);
initAllViews();
//MainActivity.showSplashScreen();
presenter.onCreate();
return rootView;
}
@Override
public void setImageAndText(Step step){
int blockNum = step.getBlock();
int stepInBlockNum = step.getIdInBlock();
taskIcons[blockNum][stepInBlockNum].setImageResource(step.getFullPath(context));
Drawable drawable = taskIcons[blockNum][stepInBlockNum].getDrawable();
if(drawable instanceof Animatable){
((Animatable) drawable).start();
}
taskNames[blockNum][stepInBlockNum].setText(step.getName());
}
@Override
public void onResume() {
super.onResume();
String title = context.getResources().getString(R.string.steps_fragment);
MainPresenter.changeToolbarTitle(title);
}
private void initAllViews(){
taskIcons[0][0] = (ImageView) rootView.findViewById(R.id.step11);
taskIcons[0][1] = (ImageView) rootView.findViewById(R.id.step12);
taskIcons[0][2] = (ImageView) rootView.findViewById(R.id.step13);
taskIcons[0][3] = (ImageView) rootView.findViewById(R.id.step14);
taskIcons[0][4] = (ImageView) rootView.findViewById(R.id.step15);
taskIcons[1][0] = (ImageView) rootView.findViewById(R.id.step21);
taskIcons[1][1] = (ImageView) rootView.findViewById(R.id.step22);
taskIcons[1][2] = (ImageView) rootView.findViewById(R.id.step23);
taskIcons[1][3] = (ImageView) rootView.findViewById(R.id.step24);
taskIcons[1][4] = (ImageView) rootView.findViewById(R.id.step25);
for(int blockNum = 0; blockNum < BLOCK_COUNT; blockNum++){
for(int stepNum = 0; stepNum < BLOCK_STEPS_COUNT; stepNum++){
taskIcons[blockNum][stepNum].setOnClickListener(getImageListener(blockNum, stepNum));
}
}
taskNames[0][0] = (TextView) rootView.findViewById(R.id.step11Name);
taskNames[0][1] = (TextView) rootView.findViewById(R.id.step12Name);
taskNames[0][2] = (TextView) rootView.findViewById(R.id.step13Name);
taskNames[0][3] = (TextView) rootView.findViewById(R.id.step14Name);
taskNames[0][4] = (TextView) rootView.findViewById(R.id.step15Name);
taskNames[1][0] = (TextView) rootView.findViewById(R.id.step21Name);
taskNames[1][1] = (TextView) rootView.findViewById(R.id.step22Name);
taskNames[1][2] = (TextView) rootView.findViewById(R.id.step23Name);
taskNames[1][3] = (TextView) rootView.findViewById(R.id.step24Name);
taskNames[1][4] = (TextView) rootView.findViewById(R.id.step25Name);
}
@NonNull
private View.OnClickListener getImageListener(int blockNum, int stepNum){
return v -> presenter.onStepClick(blockNum, stepNum);
}
@Override
public void onDestroy(){
super.onDestroy();
Log.d("mytag", "onDestroy() in StepsFragment");
//presenter.onDestroy();
//presenter = null;
}
}
TasksFragment.java (Второй фрагмент)
public class TasksFragment extends Fragment implements BaseTasksView {
public static final String ARGS_BLOCK = "Block";
public static final String ARGS_STEP = "Step";
private int block;
private int step;
private View rootView;
private BaseTasksPresenter presenter;
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(
R.layout.tasks_fragment, container, false);
presenter = new TasksPresenter();
Bundle args = getArguments();
HashMap<String, Integer> info = (HashMap<String, Integer>) args.getSerializable(ARG_INFO);
block = info.get(ARGS_BLOCK);
step = info.get(ARGS_STEP);
presenter.onCreate(this, block, step);
ImageView tasksBackArrow = (ImageView) rootView.findViewById(R.id.tasksBackArrow);
tasksBackArrow.setOnClickListener(v -> presenter.onBackArrowClick());
TextView tasksStepName = (TextView) rootView.findViewById(R.id.tasksStepName);
tasksStepName.setText(presenter.getStepName());
return rootView;
}
@Override
public void onDestroy(){
super.onDestroy();
Log.d("mytag", "onDestroy() is TasksFragment");
//presenter.onDestroy();
//presenter = null;
// TODO: Если раскоментить 2 строчки выше- появляется баг. Понять почему
}
@Override
public void showTasks(ArrayList<Task> tasks) {
final ViewPager pager = (ViewPager) rootView.findViewById(R.id.tasksFragmentViewPager);
FragmentManager fm = getActivity().getFragmentManager();
PagerAdapter textPagerAdapter = new TasksFragmentAdapter(tasks, fm);
pager.setAdapter(textPagerAdapter);
}
@Override
public Fragment getFragment() {
return this;
}
}
TasksPresenter.java (Презентер второго фрагмента)
class TasksPresenter implements BaseTasksPresenter {
private BaseTasksView view;
private BaseTasksModel model;
private int blockNum;
private int stepNum;
@Override
public ArrayList<Task> onCreate(BaseTasksView view, int blockNum, int stepNum) {
this.view = view;
this.model = new TasksModel();
Log.d("mytag", "onCreate blockNum = " + blockNum + " step = " + stepNum);
ArrayList<Task> tasks = new ArrayList<>();
this.blockNum = blockNum;
this.stepNum = stepNum;
addSubscription(model.getTaskByStep(blockNum, stepNum).subscribe(new Observer<Task>() {
@Override
public void onCompleted() {
view.showTasks(tasks);
}
@Override
public void onError(Throwable e) {
Log.d("mytag", "TasksPresenter.onCreate some error" + e);
}
@Override
public void onNext(Task task) {
tasks.add(task);
Log.d("mytag", "Next task");
}
}));
return null;
}
@Override
public void onBackArrowClick() {
view.getFragment().getActivity().onBackPressed();
//MainPresenter.changeFragment(new StepsFragment(), DONT_ADD_TO_BACKSTACK, DONT_REFRESH, DONT_HIDE_TOOLBAR);
}
@Override
public String getStepName() {
return model.getStepByNumber(blockNum, stepNum);
}
@Override
public void addSubscription(Subscription subscription) {
allSubscriptions.add(subscription);
}
@Override
public void onDestroy() {
allSubscriptions.unsubscribe();
Log.d("mytag", "onDestroy() in TasksPresenter");
}
}
Код смены фрагментов (Находится в презентере главной активити)
public static void changeFragmentWithInfo(Fragment fragment, boolean addToBackStack, boolean refresh,
boolean hideToolbar, HashMap<String, Integer> info){
Class fragmentClass = fragment.getClass();
if(currentFragmentClass != null) {
if (fragmentClass.equals(currentFragmentClass) && !refresh) {
//Log.d("mytag", "MainPresenter.changeFragment() already that fragment");
return;
}
}
currentFragmentClass = fragment.getClass();
fragmentTransaction = fragmentManager.beginTransaction();
if(addToBackStack) {
fragmentTransaction.addToBackStack(null);
}
if(info != null) {
Bundle args = new Bundle();
args.putSerializable(ARG_INFO, info);
fragment.setArguments(args);
}
changeToolbarVisibility(hideToolbar);
fragmentTransaction.setTransition(TRANSIT_FRAGMENT_FADE);
fragmentTransaction.replace(R.id.content, fragment);
fragmentTransaction.commit();
}
tasks_fragment.xml (Разметка второго фрагмента)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/tasks_fragment_background_color"
android:orientation="vertical">
<ImageView
android:id="@+id/tasksBackArrow"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:padding="5dp"
app:srcCompat="@drawable/ic_arrow_left" />
<TextView
android:id="@+id/tasksStepName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="18dp"
android:layout_toEndOf="@+id/tasksBackArrow"
android:textColor="@android:color/white"
android:textSize="16sp" />
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tasksFragmentViewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"></android.support.v4.view.ViewPager>
</RelativeLayout>
Полный стэктрэйс ошибки:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ru.timuruktus.febree, PID: 5193
java.lang.IllegalArgumentException: No view found for id 0x7f0e00e0 (ru.timuruktus.febree:id/tasksFragmentViewPager) for fragment TaskFragment{ab8ac48 #6 id=0x7f0e00e0}
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:965)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
at android.app.BackStackRecord.run(BackStackRecord.java:799)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1537)
at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:562)
at android.support.v13.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:176)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1268)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1116)
at android.support.v4.view.ViewPager$3.run(ViewPager.java:273)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:860)
at android.view.Choreographer.doCallbacks(Choreographer.java:672)
at android.view.Choreographer.doFrame(Choreographer.java:605)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:846)
at android.os.Handler.handleCallback(Handler.java:742)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:5527)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
Во фрагментах, для любых действий с фрагментами вложенными, т.е. в т.ч. в случае с ViewPager во фрагменте, надо использовать FragmentManager фрагмента, который надо получать методом getChildFragmentManager(), т.е. в вашем случае надо заменить
FragmentManager fm = getActivity().getFragmentManager();
на
FragmentManager fm = getChildFragmentManager();
Дополню ответ ЮрийСПб, у меня данная ошибка вылетала пока я не стал устанавливать код фрагменту хардкодом (была генерация id для view - заменил на 1 - см код):
view = new LinearLayout(context);
view.setLayoutParams(newViewGroup.LayoutParams
(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
view.setId(1);
view.setPadding(0,10,0,0);
fragmentManager.beginTransaction().add(1, VideoFragment.newInstance(text)).commitAllowingStateLoss();
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники