【问题标题】:Initialization Method for 'RecyclerView' crashes app when used with fragments与片段一起使用时,“RecyclerView”的初始化方法会使应用程序崩溃
【发布时间】:2019-07-02 11:47:09
【问题描述】:

我在我的应用上使用了 recyclerView 来显示来自外部存储的所有文件。在我更改它之前,它在“MainActivity.java”中实现时运行良好。

现在,我希望我的应用有一个“BottomNavigationBar”;为了做到这一点,我使用片段。问题是当我触摸菜单中的特定项目(包含 RecyclerView 的项目)时应用程序崩溃。

我将所有“this”方法更改为“.getActivity()”,但它还是崩溃了。我将其更改为“.getActivity().getApplicationContext()”,但它仍然崩溃。

抱歉,我的电脑不支持硬件加速,所以我无法正确显示错误所在。相反,我已将调试器连接到我连接的手机并设置断点。当应用程序崩溃时,调试器突出显示"RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);" 行。

这是片段代码:

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();
    }
}

[如果您需要更多代码,请告诉我]

我该如何解决这个问题?

【问题讨论】:

  • 当getView().findViewById(R.id.recyclerview) 调用onCreate(...) 时,会导致Fragment 中的NPE。请改用onViewCreated(...)
  • @Ricochet 在下面看到我的答案..这会很有帮助。

标签: android android-fragments android-recyclerview android-bottom-nav-view


【解决方案1】:
RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);

你需要使用onCreateView中膨胀的视图,而不是getView()

所以,

 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;
    }

如果需要,您可以在 initRecyclerView() 中填充 RecyclerView(或使其可见,或其他)

【讨论】:

    【解决方案2】:

    把你的代码改成这个-

    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()));
        }
    

    【讨论】:

      【解决方案3】:

      试试这个 getActivity()getView() 的实例

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

      实例

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

      【讨论】:

        【解决方案4】:

        移动下面的代码来处理权限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();
                }
            }
        

        在Fragment中,你可以在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);
            }
        

        如下更改您的initRecyclerView(),

        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()));
            }
        

        它会显示fragment页面,没有空白,

        有关Fragment的生命周期的更多说明,请参阅this

        【讨论】:

        • 这个方法有效,但现在片段什么也没有显示。所有有关权限的代码都移到了OnAtivityCreated,PermissionExists 不再调用initRecyclerView,但onViewCreated 使用您提供的新initRecyclerView...
        • 现在可以工作了吗?在onCreateView 中移动您的权限功能,或者在onViewCreated 中移动。
        • 当我触摸关注项时,应用程序不再崩溃。但是, RecyclerView 不显示任何视图。当 initRecyclerView 在主 java 脚本中定义时,它确实恢复了。我现在正面临一个空白页。 (“权限功能”是什么意思?)
        • 成功了。我意识到我忘了给布局充气。谢谢你的回答。
        • 很高兴帮助你@Ricochet
        【解决方案5】:

        移除 onCreate 方法并将逻辑移到 onCreateView 中

        【讨论】:

          【解决方案6】:

          这里的问题是您的 recyclerView 通过调用 getActivity() 进行初始化,但问题是在调用 onActivityCreated() 之前该活动不存在。

          所以它崩溃了。将onCreate() 中的所有代码移动到onActivityCreated(),它应该可以正常工作。

          【讨论】:

            猜你喜欢
            • 2013-10-06
            • 1970-01-01
            • 2018-07-30
            • 1970-01-01
            • 1970-01-01
            • 2015-04-24
            • 1970-01-01
            • 2016-04-22
            • 2010-09-20
            相关资源
            最近更新 更多