保存ArrayList不起作用

时间:2015-08-12 22:27:14

标签: java android arraylist fileoutputstream

今天我开始了我的第一个Android应用程序项目 - 当然 - 我遇到了问题。我想让一个非常简单的应用程序进入整个编程的事情,我现在在我的假期,所以我认为在我上床睡觉时醒来时会很有趣。所以它不应该那么难,而且几乎所有东西都像我想要的那样。 现在的问题是,我将日期保存在ArrayList中,因此它们显示在ListView中。我读到我无法在SharedPrefs中保存ArrayLists,我没有理解SQLite的东西,所以我决定使用FileOutputStream等。我在互联网上阅读了它并试图像他们那样做但是它根本不起作用。控制台中没有错误,但如果我关闭并重新打开应用程序,我的所有元素都将消失。 谁可以帮助我? :) (我不知道代码的哪一部分很重要,哪些不是,所以这里是整个代码)

package com.gaminggears.sleeplist.sleep;


import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Path;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class MainActivity extends AppCompatActivity{

    private ListView dataListView;
    private ListView dataListView1;
    private ArrayAdapter arrayAdapter;

    File file = new File("/mnt/sdcard/SleepApp/save.sav");
    File dir = new File("/mnt/sdcard/SleepApp");

    Date date = new Date();
    SimpleDateFormat ft = new SimpleDateFormat ("E d-M-y kk:mm");

    ArrayList<String> data = new ArrayList<String>();
    ArrayList<String> data1 = new ArrayList<String>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(!dir.exists()){
            file.mkdir();
        }

        loadDataFromFile();

        dataListView1 = (ListView) findViewById(R.id.listView2);
        dataListView = (ListView) findViewById(R.id.listView);


        arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, data);
        dataListView.setAdapter(arrayAdapter);

        arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, data1);
        dataListView1.setAdapter(arrayAdapter);

        System.out.println("\t\t" + data);
    }


    public void sleepClick(View v) {
        data.add(ft.format(date));
        arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, data);
        dataListView.setAdapter(arrayAdapter);
        saveDataToFile();
    }

    public void wakeUpClick(View v){
        data1.add(ft.format(date));
        arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, data1);
        dataListView1.setAdapter(arrayAdapter);
        saveDataToFile();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

   public void saveDataToFile(){
        try{
            FileOutputStream sF = new FileOutputStream(file);
            ObjectOutputStream save = new ObjectOutputStream(sF);
            save.writeObject(data);
            save.writeObject(data1);
            save.close();
        } catch(Exception exc){
            exc.printStackTrace();
        }
    }

    public void loadDataFromFile(){
        try{
            FileInputStream saveFile = new FileInputStream(file);
            ObjectInputStream save = new ObjectInputStream(saveFile);
            data.clear();
            data.addAll((ArrayList) save.readObject());

            data1.clear();
            data1.addAll((ArrayList) save.readObject());
            save.close();
        } catch(Exception exc) {
            exc.printStackTrace();
        }
    }

}

编辑:更新了代码。现在我的错误是&#34; java.io.FileNotFoundException:/mnt/sdcard/SleepApp/save.sav:open failed:EACCES(Permission denied)&#34;。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

你的代码有点遍布。以下是主要内容:

  1. 您应该做的是创建两个方法:

    • saveDataToFile。
    • LoadDataFromFile。
  2. 查看API您可能会注意到,在共享偏好设置中,您可以调用putStringSet 这可能非常方便。看看这个。

  3. 尝试始终指定您在列表中保留的对象类型。在你的情况下,它是一个字符串,所以它应该是这样的:

    ArrayList<String> data = new ArrayList<>();
    
  4. 删除“main”方法。不会进入细节,但基本上它在这里没用。只需确保首先将其功能复制到“LoadDataFromFile”方法。

  5. 我猜你在你的活动的布局xml文件中设置了“onCLick”属性来调用“buttonOnClick”和“buttonOnClick1”。将函数名称更改为更加用户友好的名称,例如“saveButtonClick”和“loadButtonClick”。在每一个中调用您在第1部分中创建的受尊重的方法。
  6. 您遇到的最后一个问题是,即使您正确保存并加载数据,也不会显示它,因为您覆盖了要显示的数据的对象。您应该做什么而不是覆盖是清除以前的数据和添加新数据。它应该是这样的:

    data.clear();
    data.addAll((ArrayList) save.readObject());
    
  7. 希望这些笔记能为您提供一些指导。如果您有任何问题,我会尽力澄清。

    编辑:(对您的编辑)
    你得到错误的原因有两个:

    1. 需要写入文件的权限。 基本上将以下内容添加到清单中:

      <uses-permission  android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      

      更多信息here

    2. 文件和路径不存在。您不能简单地写出文件的名称,而是提供完整的路径。为此,请首先使用以下命令保存设备外部存储根路径:

      private static final String ROOT_PATH = Environment.getExternalStorageDirectory();
      private static final String FILE_NAME = "SaveFile.sav";
      

      然后在你的FileInputStream和FileOutputStream中使用根路径和文件名,用“/”分隔,如下所示:

      new FileInputStream(ROOT_PATH + "/" + FILE_NAME);
      

      在子目录中写入文件时,你必须做的另一件事是:在失踪的父母上调用mkdirmkdirs 来创建失踪的父母或父母。例如:

      File file = new File(ROOT_PATH + "/" + "SOME_FOLDER");
      file.mkdirs();
      
    3. 祝你好运。

答案 1 :(得分:0)

您必须创建自己的类/对象,然后实现Parcelable接口,继续使用它,并在使用bundle发送时传递,或者只是重新创建活动/片段,以重新获得。

看看这个答案:Android: How to implement Parcelable to my objects?

另一个答案: Save ArrayList to SharedPreferences

问候。