You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

写入文件后RecyclerView无法显示数据的技术问题咨询

问题:写入JSON到文件后RecyclerView无法显示数据

问题背景

我在Android项目中尝试把JSON数据同时写入文件并在RecyclerView中展示,但遇到了一个奇怪的问题:

  • 不添加bw.write()和bw.close()时,RecyclerView能正常显示数据
  • 添加这两行代码后,数据成功写入文件,但RecyclerView完全不显示内容

以下是我的相关代码:

1. 创建目录与文件的代码

public void filecreation() throws IOException { 
    File mediaStorageDir = new File(getActivity().getFilesDir() + "/" + "Zerribelum"); 
    if (!mediaStorageDir.exists()) { 
        if (!mediaStorageDir.mkdirs()) { 
            Log.d("App", "failed to create directory"); 
        } else { 
            Log.d("Apppppp", "create directory"); 
            File textfolder = new File(mediaStorageDir, "Text"); 
            if (!textfolder.exists()) { 
                textfolder.mkdirs(); 
                File newtext = new File(textfolder, "dummy.txt"); 
                stream = new FileOutputStream(newtext); 
                bw = new BufferedWriter(new OutputStreamWriter(stream)); 
            } 
            File imagefolder = new File(mediaStorageDir, "Image"); 
            if (!imagefolder.exists()) { 
                imagefolder.mkdirs(); 
            } 
            File videofolder = new File(mediaStorageDir, "Video"); 
            if (!videofolder.exists()) { 
                videofolder.mkdirs(); 
            } 
        } 
    } 
}

2. 处理JSON并写入文件、更新RecyclerView的代码

try { 
    JSONArray mJsonTopicArray = mJsonObject.getJSONArray(AppConstants.APIKeys.TOPICS_LIST); 
    for (int i = 0; i < mJsonTopicArray.length(); i++) { 
        Topics mTopics = new Topics(); 
        mTopics.setId(mJsonTopicArray.getJSONObject(i).getString(AppConstants.APIKeys.ID)); 
        mTopics.setTitle(mJsonTopicArray.getJSONObject(i).getString(AppConstants.APIKeys.TOPICS)); 
        mTopics.setImage(mJsonTopicArray.getJSONObject(i).getString(AppConstants.APIKeys.TOPICS_IMAGE)); 
        mTopics.setDescription(mJsonTopicArray.getJSONObject(i).getString(AppConstants.APIKeys.DESCRIPTION)); 
        mTopicsArrayList.add(mTopics); 
        bw.write(mJsonTopicArray.getJSONObject(i).getString(AppConstants.APIKeys.DESCRIPTION)); 
        bw.newLine(); 
    } 
    bw.close(); 
    mCategoryListRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 
    mCategoryListRecyclerView.setHasFixedSize(true); 
    mCategoryListRecyclerView.setAdapter(new ParallaxRecyclerAdapter(context, HomeFragment.this, mTopicsArrayList)); 
} catch (JSONException e) { 
    e.printStackTrace(); 
} catch (Exception e) { 
    e.printStackTrace(); 
}

注:已经初始化了public FileOutputStream stream;和public BufferedWriter bw;


问题根源分析

兄弟,我一眼就揪出问题所在了——你的BufferedWriter初始化逻辑有严重漏洞,而且宽泛的异常处理把关键错误给掩盖了!

仔细看你的filecreation()方法:

  1. 只有当Zerribelum目录不存在、并且成功创建的情况下,才会进入初始化bw的分支
  2. 如果Text目录已经存在(比如第二次运行APP),也不会初始化bw

这就导致:只要不是第一次全新安装运行APP,bw都会是null!这时候你调用bw.write()或bw.close(),直接就会抛出NullPointerException,但你的catch (Exception e)只是打印堆栈,不会中断流程?不对——实际上抛出异常后,try块里后面的RecyclerView初始化代码根本不会执行!

你以为数据成功写入文件?那只有第一次运行时才会发生,第二次运行时bw是null,抛异常后数据根本没写入,RecyclerView的代码也没执行,所以才会出现“写入文件后RecyclerView不显示”的假象。


解决方案

1. 修复BufferedWriter的初始化逻辑

不管目录是否已经存在,都要确保bw被正确初始化,同时用更安全的路径构造方式:

public void filecreation() throws IOException { 
    // 用File的构造函数拼接路径,避免手动拼接出现错误
    File mediaStorageDir = new File(getActivity().getFilesDir(), "Zerribelum"); 
    // 确保目录存在,不存在就创建
    if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
        Log.d("App", "failed to create directory");
        throw new IOException("Failed to create directory: " + mediaStorageDir.getAbsolutePath());
    }

    File textfolder = new File(mediaStorageDir, "Text");
    if (!textfolder.exists() && !textfolder.mkdirs()) {
        Log.d("App", "failed to create Text directory");
        throw new IOException("Failed to create Text directory: " + textfolder.getAbsolutePath());
    }

    File newtext = new File(textfolder, "dummy.txt");
    // 如果需要追加内容,把第二个参数改成true
    stream = new FileOutputStream(newtext); 
    bw = new BufferedWriter(new OutputStreamWriter(stream)); 

    // 其他目录创建逻辑不变
    File imagefolder = new File(mediaStorageDir, "Image");
    if (!imagefolder.exists()) {
        imagefolder.mkdirs();
    }
    File videofolder = new File(mediaStorageDir, "Video");
    if (!videofolder.exists()) {
        videofolder.mkdirs();
    }
}

2. 优化异常处理,确保RecyclerView代码能执行

不要用catch (Exception e)这种大而化之的捕获,要精准捕获异常并打印详细信息,同时确保bw初始化后再使用:

try { 
    // 先确保文件和流初始化完成
    filecreation();

    JSONArray mJsonTopicArray = mJsonObject.getJSONArray(AppConstants.APIKeys.TOPICS_LIST); 
    mTopicsArrayList.clear(); // 先清空列表,避免重复添加旧数据
    for (int i = 0; i < mJsonTopicArray.length(); i++) { 
        JSONObject topicObj = mJsonTopicArray.getJSONObject(i); // 提取出来,减少重复调用
        Topics mTopics = new Topics(); 
        mTopics.setId(topicObj.getString(AppConstants.APIKeys.ID)); 
        mTopics.setTitle(topicObj.getString(AppConstants.APIKeys.TOPICS)); 
        mTopics.setImage(topicObj.getString(AppConstants.APIKeys.TOPICS_IMAGE)); 
        mTopics.setDescription(topicObj.getString(AppConstants.APIKeys.DESCRIPTION)); 
        mTopicsArrayList.add(mTopics); 

        // 写入文件
        bw.write(topicObj.getString(AppConstants.APIKeys.DESCRIPTION)); 
        bw.newLine(); 
    } 

    // 先刷新流,确保数据写入文件,再关闭
    bw.flush();
    bw.close();
    stream.close();

    // 现在这部分代码肯定能执行到
    mCategoryListRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 
    mCategoryListRecyclerView.setHasFixedSize(true); 
    ParallaxRecyclerAdapter adapter = new ParallaxRecyclerAdapter(context, HomeFragment.this, mTopicsArrayList);
    mCategoryListRecyclerView.setAdapter(adapter);
    adapter.notifyDataSetChanged(); // 显式通知数据变化,确保RecyclerView更新

} catch (JSONException e) { 
    Log.e("JSON_ERROR", "解析JSON失败", e); 
} catch (IOException e) { 
    Log.e("FILE_ERROR", "文件操作失败", e); 
} catch (NullPointerException e) {
    Log.e("NULL_ERROR", "BufferedWriter未初始化", e);
}

3. 额外优化建议

  • 不要把stream和bw声明为全局变量,最好在方法内部声明,避免资源泄漏
  • 使用try-with-resources语法,自动关闭流,不用手动调用close():
try (FileOutputStream stream = new FileOutputStream(newtext);
     BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(stream))) {
    // 写入文件的逻辑
} catch (IOException e) {
    Log.e("FILE_ERROR", "写入文件失败", e);
}

内容的提问来源于stack exchange,提问作者anju jo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:48:56