Robert Vogl
Robert Vogl

Reputation: 250

Cannot Call New Fragment Without Getting a Null Reference Error

I have been trying to call a new fragment from a Recycler View, but I keep getting a Attempt to invoke virtual method androidx.fragment.app.FragmentManager androidx.appcompat.app.AppCompatActivity.getSupportFragmentManager() on a null object reference

I have tried the code in the following Stackoverflow articles:

How to pass Bundle from Fragment to Fragment

how to move from one fragment to another fragment on button click

I am not sure what I am doing wrong. I am hoping someone can help me with this.

Adapter Code to Call New Fragment:

@Override
        public void onClick(View v) {

            String albumId = String.valueOf(albumList.get(getAdapterPosition()).safeGetFirstSong().albumId);
            Log.i(TAG,"INFO - ALBUMADAPTER is passing albumId: "+albumId);


            FragmentManager fragmentManager = ((AppCompatActivity)context).getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            Fragment fragment = null;
            Bundle bundle = new Bundle();
            bundle.putInt(EXTRA_ALBUM_ID, Math.toIntExact(albumList.get(getAdapterPosition()).safeGetFirstSong().albumId));
            fragment.setArguments(bundle);

            transaction.setCustomAnimations(R.anim.layout_fad_in,R.anim.layout_fad_out,
                    R.anim.layout_fad_in,R.anim.layout_fad_out);

            transaction.hide(Objects.requireNonNull(((AppCompatActivity) context).getSupportFragmentManager()
                    .findFragmentById(R.id.main_container)));
            transaction.add(R.id.main_container, fragment);
            transaction.addToBackStack(null).commit();

            //Intent intent = new Intent(context, AlbumDetails.class);
            //intent.putExtra("albumId", albumList.get(getAdapterPosition()).safeGetFirstSong().albumId);
            //context.startActivity(intent);


        }

Fragment Code:

public class AlbumDetailsFragment extends Fragment{

    Bundle bundle = getArguments();
    int s = bundle.getInt("album_id");

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.album_details_fragment, null);
        return root;
    }
}

Logcat:

2020-11-09 07:43:49.428 13172-13172/com.example.audioplayer E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.audioplayer, PID: 13172
    java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.fragment.app.FragmentManager androidx.appcompat.app.AppCompatActivity.getSupportFragmentManager()' on a null object reference
        at com.example.audioplayer.adapters.AlbumAdapter$AlbumViewHolder.onClick(AlbumAdapter.java:95)
        at android.view.View.performClick(View.java:6294)
        at android.view.View$PerformClick.run(View.java:24770)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

AlbumAdapter:

public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.AlbumViewHolder> {

    private List<Album> albumList;
    //private Context context;
    private AppCompatActivity context;

    private static final String EXTRA_ALBUM_ID = "album_id";

    public AlbumAdapter(List<Album> albumList) {
        this.albumList = albumList;
        this.context = context;
    }

    @NonNull
    @Override
    public AlbumViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new AlbumViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.single_album_gride_item, parent, false));
    }

    protected String getAlbumTitle(Album album) {
        return album.getTitle();
    }

    @Override
    public void onBindViewHolder(@NonNull AlbumViewHolder holder, int position) {
        Album album = albumList.get(position);

        if(album!=null) {
            holder.albumName.setText(getAlbumTitle(album));
            holder.albumArtist.setText(album.getArtistName());

            Picasso.get().load("content://media/external/audio/albumart/"+album.safeGetFirstSong().albumId).placeholder(R.drawable.album).error(R.drawable.album)
                    .into(holder.albumArt);
        }
    }

    @Override
    public int getItemCount() {
        return albumList!=null?albumList.size():0;
    }

    public class AlbumViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        private ImageView albumArt;
        private TextView albumName, albumArtist;

        public AlbumViewHolder(@NonNull View itemView) {
            super(itemView);

            albumArt = (ImageView)itemView.findViewById(R.id.albumArt);
            albumName = (TextView)itemView.findViewById(R.id.albumName);
            albumArtist = (TextView)itemView.findViewById(R.id.artistName);

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {

            String albumId = String.valueOf(albumList.get(getAdapterPosition()).safeGetFirstSong().albumId);
            Log.i(TAG,"INFO - ALBUMADAPTER is passing albumId: "+albumId);


            FragmentManager fragmentManager = context.getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            Fragment fragment = null;
            Bundle bundle = new Bundle();
            bundle.putInt(EXTRA_ALBUM_ID, Math.toIntExact(albumList.get(getAdapterPosition()).safeGetFirstSong().albumId));
            fragment.setArguments(bundle);

            transaction.setCustomAnimations(R.anim.layout_fad_in,R.anim.layout_fad_out,
                    R.anim.layout_fad_in,R.anim.layout_fad_out);

            transaction.hide(Objects.requireNonNull(((AppCompatActivity) context).getSupportFragmentManager()
                    .findFragmentById(R.id.main_container)));
            transaction.add(R.id.main_container, fragment);
            transaction.addToBackStack(null).commit();
        }

    }
}

UPDATE _ TWO ADDITIONAL ERRORS CREATED BY CHANGE

AlbumFragment Code

public class AlbumFragment extends Fragment {

    private RecyclerView recyclerView;
    private AlbumAdapter albumAdapter;

    int spanCount = 3; // 3 columns
    int spacing = 20; // 50px
    boolean includeEdge = true;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.album_fragment, container, false);
        recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), spanCount));
        new LoadData().execute("");
        return view;
    }

    public class LoadData extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... strings) {
            if (getActivity() != null) {
                albumAdapter = new AlbumAdapter(new AudioLoader().getAllAlbums(getActivity()));
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String s) {
            recyclerView.setAdapter(albumAdapter);
            if(getActivity()!=null) {
                recyclerView.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge));
            }
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
    }
}

Error

Task :app:compileDebugJavaWithJavac FAILED C:\Users\rvogl\Desktop\audioPlayer\app\src\main\java\com\example\audioplayer\fragments\AlbumFragment.java:42: error: constructor AlbumAdapter in class AlbumAdapter cannot be applied to given types; albumAdapter = new AlbumAdapter(new AudioLoader().getAllAlbums(getActivity())); ^ required: AppCompatActivity,List found: List reason: actual and formal argument lists differ in length

AlbumSongFragment Code:

public class AlbumSongsFragment extends Fragment {

    private long albumId;

    private AlbumAdapter albumAdapter;
    private RecyclerView recyclerView;

    private CollapsingToolbarLayout collapsingToolbarLayout;
    private Album album;

    private ImageView smallAlbumArt, bigAlbumArt;
    private TextView albumName, artistName, albumDetails;


    public static AlbumSongsFragment newInstance(long id) {

        Bundle args = new Bundle();
        args.putLong("_ID", id);
        AlbumSongsFragment fragment = new AlbumSongsFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@NonNull Bundle savedInstanceState) {

        albumId = getArguments().getLong("_ID");
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.album_details_fragment, container, false);
        recyclerView = (RecyclerView)view.findViewById(R.id.recyclerView);

        recyclerView.setLayoutManager(new LinearLayoutManager(getContext().getApplicationContext()));
        recyclerView.setHasFixedSize(true);
        new LoadData().execute("");
        return view;
    }

    public class LoadData extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... strings) {
            if(getActivity()!=null) {
                albumAdapter=new AlbumAdapter(Collections.singletonList(new AudioLoader().getAlbum(getActivity(), albumId)));
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String s) {
            if(getActivity()!=null) {
                recyclerView.setAdapter(albumAdapter);
            }

        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
    }
}

Error

C:\Users\rvogl\Desktop\audioPlayer\app\src\main\java\com\example\audioplayer\fragments\AlbumSongsFragment.java:76: error: constructor AlbumAdapter in class AlbumAdapter cannot be applied to given types; albumAdapter=new AlbumAdapter(Collections.singletonList(new AudioLoader().getAlbum(getActivity(), albumId))); ^ required: AppCompatActivity,List found: List reason: actual and formal argument lists differ in length Note: Some input files use or override a deprecated API. Note: Recompile with -Xlint:deprecation for details.

As Rquested here is the code snipit that is causing an issue:

public class LoadData extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... strings) {
            if (getActivity() != null) {
                albumAdapter = new AlbumAdapter(this,new AudioLoader().getAllAlbums(getActivity()));
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String s) {
            recyclerView.setAdapter(albumAdapter);
            if(getActivity()!=null) {
                recyclerView.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge));
            }
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
    }

Upvotes: 1

Views: 266

Answers (1)

Levente Guly&#225;s
Levente Guly&#225;s

Reputation: 66

In AlbumAdapter use :

private AppCompatActivity context;

and give the activity context in arguments of AlbumAdapter constructor like:

public AlbumAdapter(AppCompatActivity ctx,List<Album> albumList) {
    this.albumList = albumList;
    this.context = ctx;
}

and then you can use

context.getSupportFragmentManagger();

Upvotes: 1

Related Questions