2015-08-12 3 views
-3

Сегодня я начал свой первый Android-проект и, конечно же, у меня возникла проблема. Я хочу, чтобы действительно простое приложение действительно попало во все дело программирования, и сейчас я в отпуске, поэтому я подумал, что было бы интересно сохранить время, когда я ложись спать/когда я просыпаюсь. Так что это не должно быть так сложно, и почти все работает так, как я хочу. Теперь проблема в том, что я сохраняю свои даты в ArrayList, поэтому они отображаются в ListView. Я читал, что я не могу сохранить ArrayLists в SharedPrefs, я не понял предмет SQLite, поэтому решил использовать FileOutputStream и т. Д. Я читал об этом в Интернете и пытался делать все, как они, но он просто не работает , В консоли нет ошибки, но если я закрою и снова открою приложение, все мои элементы исчезнут. Кто может мне помочь? :) (я не знаю, какая часть кода является важным, а что нет, так вот весь код)Сохранение ArrayList не работает

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

} 

EDIT: обновил код. Теперь моя ошибка: «java.io.FileNotFoundException: /mnt/sdcard/SleepApp/save.sav: open failed: EACCES (Permission denied)». Есть идеи?

+0

Возьмите каждую строку этого кода, отложите ее в сторону. Напишите программу, которая сохраняет ** любые ** данные в файл с помощью 'FileOutputStream'. Затем, если это работает, измените его, чтобы сохранить ** любую ** дату. Затем, как только это сработает, вернитесь к этой программе и посмотрите, можете ли вы ее исправить самостоятельно. – durron597

+0

Распечатывает ли трассировку стека? – immibis

+0

Возьмите совет выше, а также посмотрите на жизненный цикл Android. В отличие от обычной Java-программы, где точка входа в java является общедоступной void main (string [] args), Android не работает так, но вы можете сказать, что ее эквивалент будет onCreate() –

ответ

1

Ваш код немного повсюду. Вот основные вещи:

  1. Что вы должны сделать, это создать 2 метода:

    • saveDataToFile.
    • LoadDataFromFile.
  2. глядя на API, вы можете заметить, что в общих настройках вы можете использовать putStringSet.
    Это может быть очень удобно. проверьте это.

  3. Старайтесь всегда указывать тип объекта, который вы сохраняете в своих списках. В вашем случае это строка, поэтому она должна выглядеть следующим образом:

    ArrayList<String> data = new ArrayList<>(); 
    
  4. Удалить «основной» метод. Не собираюсь вдаваться в подробности, но в основном это бесполезно здесь. Просто убедитесь, что вы сначала скопировали его функциональность в метод LoadDataFromFile.

  5. Я думаю, вы установили атрибут «onCLick» в XML-файле макета вашей деятельности, чтобы вызвать «buttonOnClick» и «buttonOnClick1». Измените имена функций на более удобные для пользователя, такие как «saveButtonClick» и «loadButtonClick». В каждом из них вызывается метод, который вы создали в разделе 1.
  6. Последняя проблема заключается в том, что даже если вы правильно сохраните и загрузите данные, она никогда не будет отображаться, потому что вы переопределяете объект данных, которые вы хотите для отображения. то, что вы должны делать вместо переопределения, - это очистка предыдущих данных и добавление новых данных. Он должен выглядеть следующим образом:

    data.clear(); 
    data.addAll((ArrayList) save.readObject()); 
    

Надежда эти ноты даст вам несколько направлений. Если у вас есть какие-либо вопросы, я сделаю все возможное, чтобы уточнить.

EDIT: (для правки)
Вы получаете ошибку из-за двух причин: разрешения

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

    Другая вещь, которую вы должны сделать при записи в файл в подкаталоги, чтобы вызвать mkdir или mkdirsна отсутствующих родителей создать отсутствующий родитель или родители. Например:

    File file = new File(ROOT_PATH + "/" + "SOME_FOLDER"); 
    file.mkdirs(); 
    

Удачи.

+0

Хорошо! Спасибо чувак! Много советов, и я попробую их всех. У меня уже был после Array, но удаление его ничего не меняло, поэтому я так и оставил его. Как я уже упоминал ранее, я уже пробовал это без основного класса, но он не работал, поэтому я просто попробовал. И кнопки arent сохраняют и загружают, они засыпают и просыпаются, но я получаю вашу точку :) Но где я должен добавить data.clear ...? – GamingGears

+0

И позвольте мне объяснить очень быстро: у меня есть ListViews с одной кнопкой в ​​списке. Первый список содержит строки из массива «данные», а второй список содержит «data1». Мои имена не так удобны для пользователя, но я не ожидал, что мне придется поделиться им с вами, поэтому я подумал, что это будет неактуально. – GamingGears

+0

Ну, я попытался использовать все ваши советы и изменил некоторые вещи, но он все еще не работает.Такая же проблема, как всегда. Heres мой код: http://pastebin.com/Y2n2w8Et – GamingGears

0

Вы должны создать свой собственный класс/объект, а затем реализовать интерфейс Parcelable, чтобы продолжать использовать это и передавать, когда вы отправляете с пакетом или просто сохраняете восстановленную активность/фрагмент, чтобы получить снова.

Посмотрите этот ответ: Android: How to implement Parcelable to my objects?

Другой ответ: Save ArrayList to SharedPreferences

С уважением.

+1

Спасибо! Но я думаю, что FileOutputStream - действительно хорошая возможность, и я просто использую это неправильно. Вы не знаете, что мне нужно изменить? Это мой код сейчас: http://pastebin.com/Y2n2w8Et – GamingGears

+0

Я вижу ваш код, бит i havent использовал этот метод для сохранения данных. Я рекомендую использовать sqlite. Если вы не хотите создавать свои таблицы и методы db вручную, используйте greendao или ormlite, оба они хороши. И поверьте мне, что вы должны попытаться это узнать, не complicares. С уважением –

Смежные вопросы