Search code examples
androidandroid-fragmentsandroid-recyclerviewandroid-bottom-nav-view

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


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 ?


Solution

  • 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