1

I am implementing navigation between Fragments from different flows (single-activity architecture with flow fragments) meaning from one nested graph to another. I am trying to pass one testID argument using Safe Args. In my origins Fragment I use generated class to create action to further set parameter:

LevelFlowFragmentDirections.ActionGlobalTestFlowFragment action = LevelFlowFragmentDirections.actionGlobalTestFlowFragment();
action.setTestID(1);

However, when I run the project it shows this error:

error: cannot find symbol

Here is what my project structure looks like:

project structure

LevelFlowFragment.java code:

package kz.rating.onaikazakh.presentation.ui.fragments.levelflow;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import kz.rating.onaikazakh.NavGraphDirections;
import kz.rating.onaikazakh.R;
import kz.rating.onaikazakh.presentation.ui.recyclerviews.section.SectionAdapter;
import kz.rating.onaikazakh.presentation.ui.utils.NavUtils;

public class LevelFlowFragment extends Fragment implements View.OnClickListener{


    private NavController navController;
    LevelsViewModel vm;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*vm = new ViewModelProvider(this).get(LevelsViewModel.class);
        vm.data.observe(this, data -> {
            if (data!=null) adapter = new SectionAdapter(this, data);
        });*/
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.flow_fragment_level, container, false);

        RecyclerView levelsRecView = rootView.findViewById(R.id.recyclerView_test_list);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        levelsRecView.setLayoutManager(layoutManager);
        int scrollposition = ((LinearLayoutManager) levelsRecView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
        levelsRecView.scrollToPosition(scrollposition);
        SectionAdapter adapter = new SectionAdapter(this, new String[]{"level 1", "level 2", "level 3"});
        levelsRecView.setAdapter(adapter);

        return rootView;
    }


    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        navController = Navigation.findNavController(view);

        Button button_skip = getView().findViewById(R.id.button_test_skip);
        button_skip.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        NavUtils.navigate(R.id.action_global_mainFlowFragment, this);
    }

    public void onViewHolderClickListener(String level){
        Bundle bundle = new Bundle();
        LevelFlowFragmentDirections.ActionGlobalTestFlowFragment action = LevelFlowFragmentDirections.actionGlobalTestFlowFragment();
        NavDirections directions = LevelFlowFragmentDirections.actionGlobalTestFlowFragment();
//temporary implementation
        switch(level){
            case "level 1":
                action.setTestID(1);
                bundle.putInt("testID", 1);
                break;
            case "level 2":
                action.setTestID(2);
                bundle.putInt("testID", 2);
                break;
            case "level 3":
                action.setTestID(3);
                bundle.putInt("testID", 3);
                break;
        }
        NavUtils.navigate(R.id.action_global_testFlowFragment, this, bundle);

    }


}

Main graph nav_graph.xml:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    tools:ignore="InvalidNavigation"
    app:startDestination="@id/langFlowFragment">

    <action
        android:id="@+id/action_global_signFlowFragment"
        app:destination="@id/signFlowFragment"
        app:popUpTo="@id/nav_graph" />

    <action
        android:id="@+id/action_global_mainFlowFragment"
        app:destination="@id/mainFlowFragment"
        app:popUpTo="@id/nav_graph" />

    <action
        android:id="@+id/action_global_levelFlowFragment"
        app:destination="@id/levelFlowFragment"
        app:popUpTo="@id/nav_graph" />

    <action
        android:id="@+id/action_global_langFlowFragment"
        app:destination="@id/langFlowFragment"
        app:popUpTo="@id/nav_graph" />

    <action
        android:id="@+id/action_global_testFlowFragment"
        app:destination="@id/testFlowFragment"
        app:popUpTo="@id/nav_graph">
        <argument
            android:name="testID"
            app:argType="integer"
            android:defaultValue="0" />
    </action>

    <fragment
        android:id="@+id/mainFlowFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.mainflow.MainFlowFragment"
        android:label="flow_fragment_main"
        tools:layout="@layout/flow_fragment_main" />

    <fragment
        android:id="@+id/signFlowFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.signflow.SignFlowFragment"
        android:label="flow_fragment_sign"
        tools:layout="@layout/flow_fragment_sign" />

    <fragment
        android:id="@+id/levelFlowFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.levelflow.LevelFlowFragment"
        android:label="flow_fragment_level"
        tools:layout="@layout/flow_fragment_level" />

    <fragment
        android:id="@+id/langFlowFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.langflow.LanguageFlowFragment"
        android:label="flow_fragment_lang"
        tools:layout="@layout/flow_fragment_lang" />

    <fragment
        android:id="@+id/testFlowFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.testflow.TestFlowFragment"
        android:label="flow_fragment_test"
        tools:layout="@layout/flow_fragment_test" >
        <argument
            android:name="testID"
            app:argType="integer"
            android:defaultValue="0" />
    </fragment>

</navigation>

test_graph.xml:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/test_graph"
    app:startDestination="@id/questionFragment">

    <fragment
        android:id="@+id/questionFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.testflow.question.QuestionFragment"
        android:label="fragment_question"
        tools:layout="@layout/fragment_test_question">
        <action
            android:id="@+id/action_questionFragment_to_answerFragment"
            app:destination="@id/answerFragment" />
        <argument
            android:name="testID"
            app:argType="integer"
            android:defaultValue="0" />

    </fragment>

    <fragment
        android:id="@+id/answerFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.testflow.answer.AnswerFragment"
        android:label="fragment_answer"
        tools:layout="@layout/fragment_test_answer">
        <action
            android:id="@+id/action_answerFragment_to_questionFragment"
            app:destination="@id/questionFragment" />
        <action
            android:id="@+id/action_answerFragment_to_completedFragment"
            app:destination="@id/completedFragment" />

    </fragment>

    <fragment
        android:id="@+id/completedFragment"
        android:name="kz.rating.onaikazakh.presentation.ui.fragments.testflow.completion.CompletionFragment"
        android:label="fragment_completed"
        tools:layout="@layout/fragment_test_complete">

        <action
            android:id="@+id/action_completedFragment_to_questionFragment"
            app:destination="@id/questionFragment" />
    </fragment>

</navigation>

flow_fragment_test.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">


    <RelativeLayout
        android:id="@+id/relativeLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/wave_imageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:scaleType="fitXY"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/wave" />

    </RelativeLayout>

    <FrameLayout
        android:id="@+id/container_test"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:fitsSystemWindows="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginEnd="@dimen/activity_horizontal_margin"
        android:layout_marginStart="@dimen/activity_horizontal_margin"
        android:layout_marginTop="@dimen/activity_top_margin"
        android:layout_marginBottom="@dimen/activity_bottom_margin">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment_test"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/test_graph" />

    </FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

build.gradle :app:

apply plugin: 'com.android.application'
apply plugin: 'androidx.navigation.safeargs'

android {
    compileSdkVersion 33
    buildToolsVersion "30.0.2"

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    lintOptions {

        checkReleaseBuilds false

    }

    defaultConfig {
        applicationId "kz.rating.onaikazakh"
        minSdkVersion 24
        targetSdkVersion 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    buildFeatures {
        viewBinding = true
    }

    sourceSets {
        main {
            java {
                srcDirs += 'build/generated/source/navigation-args'
            }
        }
    }


}



dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.6.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    def nav_version = "2.5.3"

    // Java language implementation
    implementation "androidx.navigation:navigation-fragment:$nav_version"
    implementation "androidx.navigation:navigation-ui:$nav_version"

    // Kotlin
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

    // Feature module Support
    implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

    // Testing Navigation
    androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

    // Jetpack Compose Integration
    implementation "androidx.navigation:navigation-compose:$nav_version"


    implementation project(path: ':domain')
    implementation project(path: ':data')
}

build.gradle :project:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.2'

        def nav_version = "2.5.3"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

What I have tried:

  1. Clean, Rebuild
  2. I saw Safeargs library doesnt generate direction class, and added
    sourceSets {
        main {
            java {
                srcDirs += 'build/generated/source/navigation-args'
            }
        }
    }
  1. Updated all dependencies and plugins
  2. I also saw Build error: Cannot find symbol. Points to navigation actions, but the author deleted nested graph which worked. In my case I cannot apply this solution.
  3. Saw Action is not generated in FragmentDirections when Fragment is used in a second nav graph, but I already have @+id in the action and in every graph.

6) Off-topic: later I tried another way of passing data via creating Bundle and retrieving it in both QuestionFragment and TestFlowFragment. Neither it produced errors nor passed any data. This is code from destination fragment

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        vm = new ViewModelProvider(this).get(TestSharedViewModel.class);
        int id = getArguments().getInt("testID");
        Log.v("AAA", "id is " + id);
        vm.setID(id);

    }

I would appreciate any help on resolving the problem or other ways to implement passing data between those fragments.

Edit What does a "Cannot find symbol" or "Cannot resolve symbol" error mean? Does not resolve my issue. Most of them are about wrong import, dependencies or misspelling, but these are generated classes, LevelFlowFragmentDirections.ActionGlobalTestFlowFragment was offered by IDE; when I tried to remove the LevelFlowFragmentDirections to follow official android guide it offered referencing LevelFlowFragmentDirections.ActionGlobalTestFlowFragment from different modules(?) and I tried both app and app.main. In regard to JDK and Gradle compatability, it used to be 1.8 with gradle 4.0.1, I upgraded to 11 and 7.0.2.

  • 1
    Does this answer your question? [What does a "Cannot find symbol" or "Cannot resolve symbol" error mean?](https://stackoverflow.com/questions/25706216/what-does-a-cannot-find-symbol-or-cannot-resolve-symbol-error-mean) – Jens Apr 15 '23 at 15:23

1 Answers1

0

Finally I worked it out. For some reason IDE suggested LevelFlowFragmentDirections.ActionGlobalTestFlowFragment, whereas when I looked into the app->build->generated->source the no inner class ActionGlobalTestFlowFragment in LevelFlowFragmentDirections. Instead, there was NavGraphDirections with ActionGlobalTestFlowFragment in it.

The post suggested by @Jens did contain the answer, IDE highlights can be extremely misleading though.