Initialization Method for 'RecyclerView' crashes app when used with fragments

140 Views Asked by At

I used a recyclerView on my app to display all files from an external storage. Until I changed it, it worked fine when it was implemented in the "MainActivity.java".

Now, I want my app to have a "BottomNavigationBar"; in order to do that, I use fragments. The problem is the app crashes when I touch the specific item from the menu (the one containing the RecyclerView).

I changed all the "this" method to ".getActivity()" but it crashed anyways. I changed it to ".getActivity().getApplicationContext()" but it still crashed.

I'm sorry, my computer does not support hardware acceleration so I can't properly show what the error is. Instead, I have attached a debugger to my connected phone and set up breakpoints. The debugger highlighted the line "RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);" when the app crashed.

Here's the fragment code:

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_records, container, false);
    }

    private static final int PERMISSION_REQUEST = 1000;
    private ArrayList<String> mNames = new ArrayList<>();
    public static ArrayList<String> NbFiles = new ArrayList<>();
    public ArrayList<String> PathFiles = new ArrayList<>();

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Check if we have the permission to read storage
        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //We don't have the permission, so request it.
            ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
        }
        //We already have permission
        else {
            permissionExists();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == PERMISSION_REQUEST) {
            if (resultCode == RESULT_OK) {
                permissionExists();
            } else {
                //handle error
            }
        }
    }

    private void initRecyclerView() {
        RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);
        RecyclerViewAdapter adapter = new RecyclerViewAdapter(mNames, getActivity().getApplicationContext(), (RecyclerViewAdapter.OnNoteListener) this);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
    }

    private void permissionExists() {
        String path = Environment.getExternalStorageDirectory().toString() + "/Rapture";
        File directory = new File(path);
        boolean success = true;
        if (!directory.exists()) {
            success = directory.mkdirs();
        }
        if (success) {
            File[] arrayFiles = directory.listFiles();
            for (File file : arrayFiles) {
                mNames.add(file.getName());
                PathFiles.add(file.getPath());
                NbFiles.add(file.getName());
            }
        }
        initRecyclerView();
    }
}

[Let me know if you need more code]

How can I fix this ?

6

There are 6 best solutions below

7
Android On BEST ANSWER

Move below code for handling permission onActivityCreated

@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //We don't have the permission, so request it.
            ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
        }
        //We already have permission
        else {
            permissionExists();
        }
    }

In Fragment, you can initialize your view in onViewCreated

    // This event is triggered soon after onCreateView().
    // Any view setup should occur here.  E.g., view lookups and attaching view listeners.
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // Setup any handles to view objects here
         initRecyclerView(view);
    }

Change your initRecyclerView() like below,

private void initRecyclerView(View v) {
        RecyclerView recyclerView = v.findViewById(R.id.recyclerview);
        RecyclerViewAdapter adapter = new RecyclerViewAdapter(mNames, getActivity().getApplicationContext(), (RecyclerViewAdapter.OnNoteListener) this);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
    }

It will shows fragment page without blank,

Screenshot1

For more clarification about life cycle of Fragment, refer this

0
Joachim Haglund On

Remove the onCreate mewthod and move the logic into onCreateView

0
MSpeed On
RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);

Instead of getView(), you need to use the view inflated in onCreateView

So,

 RecyclerView recyclerView;

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_records, container, false);
        recyclerView = v.findViewById(R.id.recyclerview);
        return v;
    }

If you want, you can then populate the RecyclerView (or make it visible, or whatever) in initRecyclerView()

0
Ashish P On

try this getActivity() instance of getView()

RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);  

instance of

RecyclerView recyclerView = getActivity().findViewById(R.id.recyclerview);
0
RootZero On

Here the issue is your recyclerView initializes by calling getActivity() but the problem is that the activity does not exist until onActivityCreated() is called.

So it's crashing. Move all of that code inside onCreate() to onActivityCreated() and it should work fine.

0
Prachi Singh On

Change your code to this-

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_records, container, false);
    initRecyclerView(view);
    return view;
}



private void initRecyclerView(View view) {
        RecyclerView recyclerView = view.findViewById(R.id.recyclerview);
        RecyclerViewAdapter adapter = new RecyclerViewAdapter(mNames, getActivity().getApplicationContext(), (RecyclerViewAdapter.OnNoteListener) this);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
    }