static HashMap<> - являются ли добавленные данные статичными
static HashMap<> - являются ли добавленные данные статичными
Здравствуйте.
Мне нужно по ходу программы накапливать данные. Для этого я решил использовать в отдельном классе поле static EnumMap<MyEnum, Object> emap = new EnumMap<>(MyEnum.class);
Проблема в том, что иногда некоторые элементы key-value пропадают. Если я правильно понимаю, то проблема в том, что при объявлении static статичным является только объявленная ссылка на emap, а все позже добавленные элементы уже нестатические и следовательно могут пропадать.
Посоветуйте, плиз, что лучше применять для моей задачи: накапливать небольшое количество элементов<enum, Oject>, которые я собираю из многих фрагментов.
Спасибо.
Мне нужно по ходу программы накапливать данные. Для этого я решил использовать в отдельном классе поле static EnumMap<MyEnum, Object> emap = new EnumMap<>(MyEnum.class);
Проблема в том, что иногда некоторые элементы key-value пропадают. Если я правильно понимаю, то проблема в том, что при объявлении static статичным является только объявленная ссылка на emap, а все позже добавленные элементы уже нестатические и следовательно могут пропадать.
Посоветуйте, плиз, что лучше применять для моей задачи: накапливать небольшое количество элементов<enum, Oject>, которые я собираю из многих фрагментов.
Спасибо.
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: static HashMap<> - являются ли добавленные данные статич
EnumMap != HashMap.
P.S. ничего просто так не пропадает. Сформулируйте конкретнее что у вас там
P.S. ничего просто так не пропадает. Сформулируйте конкретнее что у вас там
Re: static HashMap<> - являются ли добавленные данные статич
Да, действительно, я заменил HashMap на EnumMap. Извините за попытку ввести Вас в заблуждение
Вот класс, в котором находится static EnumMap:
А вот пример класса, который добавляет новый элемент.
Добавление происходит в конце метода onCreateView. Сначала я создаю новый экземпляр класса
tdl = new TempDataLesson(); и затем добавляю элемент используя метод addToEnumMap.
Блин, не могу понять что я делаю не так
Вот класс, в котором находится static EnumMap:
Код: Выделить всё
package ua.sanya5791.pochemu;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.EnumMap;
import ua.sanya5791.pochemu.db.DbQueryTask;
import ua.sanya5791.pochemu.db.DbStatements.LessonInsert;
import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
/**
* Этот класс собирает в ArrayList "data" все необходимые данные для использования в запросе LESSON_INSERT;
* @author sanya
*
*/
public class TempDataLesson {
static String TAG = "DataLessonInsert";
private static final boolean isDebug = true;
//здесь объявляю
private static EnumMap<LessonInsert, Object> emap = new EnumMap<>(LessonInsert.class);
public TempDataLesson() {
}
/**
*добавляет связку key-value to HashMap;
*
*/
void addToEnumMap(LessonInsert key, Object value){
Object oldValue = emap.put(key,value);
}
/**
* делает проверку на наличие минимума необходимых элементов в HashMap.
* @param emap входящий
* @return true; Если кого-то нет, то false
*/
private boolean isValidHashMap() {
//обязательный список элементов
LessonInsert[] emapKeys = {
LessonInsert.I_PERSON_ID,
LessonInsert.I_DATE_LESSON,
LessonInsert.I_ZONE_ID,
LessonInsert.I_SUBZONE_ID,
LessonInsert.I_MATERIAL_ID,
};
if(emap.get(LessonInsert.I_PERSON_ID) == null)
MyLogger("Не хвататет обязательного поля: "
+ LessonInsert.I_PERSON_ID.toString()
+ " для выполнения запроса LESSON_INSERT");
for(LessonInsert key : emapKeys){
if(emap.get(key) == null)
MyLogger("Не хвататет обязательного поля: "
+ key.toString() + " для выполнения запроса LESSON_INSERT");
if(! emap.containsKey(key)){
MyLogger("Не хвататет обязательного поля: "
+ key.toString() + " для выполнения запроса LESSON_INSERT");
return false;
}
}
return true;
}
/**
*
* @return either completed HashMap or null;
* null in case the HashMap is not completely filled
*/
EnumMap<LessonInsert,Object> getFilled(){
//метод: вернуть заполненный HashMap
if (isValidHashMap()) {
return emap;
} else {
return null;
}
}
void clear(){
emap.clear();
}
void newEMap(){
emap=new EnumMap<>(LessonInsert.class);
}
private void MyLogger(String statement){
if (isDebug) {
Log.v(TAG, statement);
}
}
@Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
super.finalize();
clear();
}
}
Добавление происходит в конце метода onCreateView. Сначала я создаю новый экземпляр класса
tdl = new TempDataLesson(); и затем добавляю элемент используя метод addToEnumMap.
Код: Выделить всё
class FrZonesList1 extends Fragment implements MyInterfaces{
static String TAG = "sanya5791.pochemuchka.FragmentZonesList";
private static final boolean isDebug = true;
int selectedZone_id;
private Activity curActivity; //base Activity who places the fragment
private ResultSet rs;
private SimpleAdapter adapter;
private ListView lv;
private OnLvSelectListener onLvSelectListener;
private DbQueryTask<FrZonesList> getZonesTask;
private TempDataLesson tdl;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
curActivity = activity;
//check whether the calling activity has implemented OnSelectedZoneListener
try {
onLvSelectListener=(OnLvSelectListener)activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnLvSelectListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
MyLogger("onCreateView: ");
View viewF = inflater.inflate(R.layout.fragment_zones_list,
container, false);
ActionBar actionBar = curActivity.getActionBar();
actionBar.setTitle("Список зон");
lv = (ListView) viewF.findViewById(R.id.lv_out1);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
MyLogger("The item N" + position + " is selected" +
"\nIt contains" + parent.getAdapter().getItem(position));
try {
rs.absolute(position+1);
selectedZone_id = rs.getInt("ZONE_ID");
// так мы передаем через метод onSelectedZone интерфеса OnSelectedZoneListener id зоны НАЖАТОГО элемента списка lv
onLvSelectListener.onLvSelected(this, selectedZone_id);
} catch (SQLException e) {
e.printStackTrace();
}
//так я добавляю новые элементы
tdl = new TempDataLesson();
tdl.addToEnumMap(
LessonInsert.I_ZONE_ID,
selectedZone_id);
}
});
return viewF;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
MyLogger("onActivityCreated: ");
}
private void MyLogger(String statement){
if (isDebug) {
Log.v(TAG, statement);
}
}
}
Re: static HashMap<> - являются ли добавленные данные статич
Кстати, сейчас переделываю код, где метод TempDataLesson.addToEnumMap(LessonInsert, Object) я сделал static.
Так не требуется создавать экземпляр класса TempDataLesson для обращения к методу добавления addToEnumMap - может здесь собака порылась. И пропадания элементов в EnumMap пока не замечено. Но хочу разобраться в матчасти.
Так не требуется создавать экземпляр класса TempDataLesson для обращения к методу добавления addToEnumMap - может здесь собака порылась. И пропадания элементов в EnumMap пока не замечено. Но хочу разобраться в матчасти.
Re: static HashMap<> - являются ли добавленные данные статич
я не пойму, зачем тут вообще статики??
R.id.team
NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198
NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: static HashMap<> - являются ли добавленные данные статич
Когда именно они пропадают? И зачем вам метод newEMap? Этот метод затирает ваши данные в коллекции
Правильно, разберитесь в матчасти, а именно отличие статических объектов от динамических, а также отличие статических методов от динамическихНо хочу разобраться в матчасти.
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: static HashMap<> - являются ли добавленные данные статич
Я советую ни когда не использовать статик переменные, если в них хранится какая, либо нужная информация. Логику в статике можно хранить, но ни как не данные.
Для того, что бы понять свою ошибку, добавьте следующий код по нажатию на кнопку:
[syntax=java5] Thread systemExitThread = new Thread() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
runOnUiThread(new Runnable() {
public void run() {
System.exit(0);
}
});
};
};
systemExitThread .start();[/syntax] После нажатия сразу сверните приложение, через 5 секунд разверните. Активити должно восстановиться до состояния перед сворачиванием. В вашем же случае все данные будут затерты.
System.exit(0) - Имитация ситуации когда приложение находится долго в свернутом состоянии.
Для хранения данных нужно использовать Preferences, Базу данных или файл. Как бы это было не печально, но таков Android.
Для того, что бы понять свою ошибку, добавьте следующий код по нажатию на кнопку:
[syntax=java5] Thread systemExitThread = new Thread() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
runOnUiThread(new Runnable() {
public void run() {
System.exit(0);
}
});
};
};
systemExitThread .start();[/syntax] После нажатия сразу сверните приложение, через 5 секунд разверните. Активити должно восстановиться до состояния перед сворачиванием. В вашем же случае все данные будут затерты.
System.exit(0) - Имитация ситуации когда приложение находится долго в свернутом состоянии.
Для хранения данных нужно использовать Preferences, Базу данных или файл. Как бы это было не печально, но таков Android.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
Re: static HashMap<> - являются ли добавленные данные статич
Денис, да у него данные во фрагментах, их можно в любую переменную/свойство активити собирать. Зачем эти заморочки, статики вообще не пойму я.
R.id.team
NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198
NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198
Re: static HashMap<> - являются ли добавленные данные статич
Спасибо большое за разъяснения.KamiSempai писал(а):Я советую ни когда не использовать статик переменные, если в них хранится какая, либо нужная информация. Логику в статике можно хранить, но ни как не данные.
Для того, что бы понять свою ошибку, добавьте следующий код по нажатию на кнопку:
[syntax=java5] Thread systemExitThread = new Thread() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
runOnUiThread(new Runnable() {
public void run() {
System.exit(0);
}
});
};
};
systemExitThread .start();[/syntax] После нажатия сразу сверните приложение, через 5 секунд разверните. Активити должно восстановиться до состояния перед сворачиванием. В вашем же случае все данные будут затерты.
System.exit(0) - Имитация ситуации когда приложение находится долго в свернутом состоянии.
Да, я ранее уже где-то встречал информацию о том, что для хранения данных лучше не рассчитывать на static. Спасибо!!! Пересмотрю подходKamiSempai писал(а): Для хранения данных нужно использовать Preferences, Базу данных или файл. Как бы это было не печально, но таков Android.
Re: static HashMap<> - являются ли добавленные данные статич
Разобрался в своей проблеме. Дело в том, что я в TempDataLesson.finalize() добавил emap.clear() - очистку своего EnumMap. Получается, что я создавал новые экзепляры TempDataLesson из фрагментов, а когда фрагменты прибивались, то и прибивались все связанные ресурсы, а следовательно и отрабатывал TempDataLesson.finalize().
А когда я изменил метод TempDataLesson.addToEnumMap на static, то для его вызова не нужно было создавать новый экземпляр класса TempDataLesson. Следовательно при высвобождении ресурсов не вызывался метод TempDataLesson.finalize(). Т.о. проблема была workaround.
Когда я это понял, то убрал очистку Мар из TempDataLesson.finalize() и убрал static - все заработало, ура!!!
Еще раз спасибо KamiSempai. Теперь нужно будет все хранить в Preferences.
А когда я изменил метод TempDataLesson.addToEnumMap на static, то для его вызова не нужно было создавать новый экземпляр класса TempDataLesson. Следовательно при высвобождении ресурсов не вызывался метод TempDataLesson.finalize(). Т.о. проблема была workaround.
Когда я это понял, то убрал очистку Мар из TempDataLesson.finalize() и убрал static - все заработало, ура!!!
Еще раз спасибо KamiSempai. Теперь нужно будет все хранить в Preferences.
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: static HashMap<> - являются ли добавленные данные статич
Может кто мне пояснит русским языком почему статики это плохо? Я вот ни одного аргумента не услышал
Вернусь к нашим баранам. Итак, что не так со статиками? Да, я читал что мол данные в нём могут пропадать, но по факту читал единожды, в одном месте, при этом ни разу не встречал такого. Если статик теряет данные, то:
1) почему паттерн ViewHolder, объявленный как статик класс такой популярный?
2) почему статик переменные (без final префикса) также популярны?
Я знаю один минус статиков - можно получить утечку. Всё другое больше смахивает на миф, либо на адски редкие случаи чего-то там-то.
Чего?! А с этого момента поподробнее. С чего вдруг system.exit(0) - это имитация сворчачивания? Денис, ты ли это? о_О Это закрытие процесса, даже не процесса, а приложения, и он сработал так, как надо в этом коде. Нам как-то рассказывали как один человек в JavaEE приложении ввёл эту команду в простой обработчик ошибки. И эта строчка закрыла всё приложение, которое разворачивается не один десяток минут, работая на множестве серверов.После нажатия сразу сверните приложение, через 5 секунд разверните. Активити должно восстановиться до состояния перед сворачиванием. В вашем же случае все данные будут затерты.
System.exit(0) - Имитация ситуации когда приложение находится долго в свернутом состоянии.
Вернусь к нашим баранам. Итак, что не так со статиками? Да, я читал что мол данные в нём могут пропадать, но по факту читал единожды, в одном месте, при этом ни разу не встречал такого. Если статик теряет данные, то:
1) почему паттерн ViewHolder, объявленный как статик класс такой популярный?
2) почему статик переменные (без final префикса) также популярны?
Я знаю один минус статиков - можно получить утечку. Всё другое больше смахивает на миф, либо на адски редкие случаи чего-то там-то.
На сколько я помню, этот метод не рекомендуется использовать, дабы не отстрелить себе чего. Хотите освободить память? System.gc() вам в помощь.Разобрался в своей проблеме. Дело в том, что я в TempDataLesson.finalize()
Re: static HashMap<> - являются ли добавленные данные статич
Да, возвращаясь на нашим баранам и подтянув матчасть хочу изложить ход своих размышлений, а Вы поправьте, плиз.
Итак, объявлен static HashMap<T, V> hmap = new HashMap<String, String>. Это значит, что при первом обращении к его классу, hmap инициализируется в первую очередь и под него статически выделяется память. Сколько под него может быть выделно памяти? Ровно столько, сколько нужно чтобы статически хранить ссылку на hmap, к которой прикрепляется динамический объект с местом для хранения 16 ячеек.
Затем мы заполняем hmap.put("key", "value"). Это значит, что мы заполняем первые 16 ячеек, когда они закончатся будет выделен новый объект с новыми ячейками и паровозом прикрепится к статической ссылке hmap и ранее выделенным 16-ти ячейкам.
Т.е. мы имеем статическую ссылку и за ней паровоз объектов. Сборщик мусора уничтожает только те объекты, на которые нет активных ссылок в коде, а наша ссылка hmap всегда активна, а занчит и все динамические объекты будут жить до тех пор, пока мы не сделаем hmap.clear(). И эту очистку нужно делать самостоятельно, если хочешь избежать "мифических утечек".
И конечно, если приложение будет остановлено системой, то все линки на объекты утратят актуальность и будут очищены сборщиком мусора - следовательно и очиститься нашь static hmap.
Вроде так. Поправьте, если я где ошибаюсь.
Итак, объявлен static HashMap<T, V> hmap = new HashMap<String, String>. Это значит, что при первом обращении к его классу, hmap инициализируется в первую очередь и под него статически выделяется память. Сколько под него может быть выделно памяти? Ровно столько, сколько нужно чтобы статически хранить ссылку на hmap, к которой прикрепляется динамический объект с местом для хранения 16 ячеек.
Затем мы заполняем hmap.put("key", "value"). Это значит, что мы заполняем первые 16 ячеек, когда они закончатся будет выделен новый объект с новыми ячейками и паровозом прикрепится к статической ссылке hmap и ранее выделенным 16-ти ячейкам.
Т.е. мы имеем статическую ссылку и за ней паровоз объектов. Сборщик мусора уничтожает только те объекты, на которые нет активных ссылок в коде, а наша ссылка hmap всегда активна, а занчит и все динамические объекты будут жить до тех пор, пока мы не сделаем hmap.clear(). И эту очистку нужно делать самостоятельно, если хочешь избежать "мифических утечек".
И конечно, если приложение будет остановлено системой, то все линки на объекты утратят актуальность и будут очищены сборщиком мусора - следовательно и очиститься нашь static hmap.
Вроде так. Поправьте, если я где ошибаюсь.
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: static HashMap<> - являются ли добавленные данные статич
Что значит хранить статически ссылку? Ссылка она и в Африке ссылка на сколько мне известно, и не имеет различий динамически и статическичтобы статически хранить ссылку на hmap
Дакогда они закончатся будет выделен новый объект с новыми ячейками и паровозом прикрепится к статической ссылке hmap и ранее выделенным 16-ти ячейкам.
Да.Сборщик мусора уничтожает только те объекты, на которые нет активных ссылок в коде, а наша ссылка hmap всегда активна, а занчит и все динамические объекты будут жить до тех пор, пока мы не сделаем hmap.clear()
Да, либо использовать WeakReferenceИ эту очистку нужно делать самостоятельно, если хочешь избежать "мифических утечек".
Если приложение умрёт, то по определению у вас ничего не останется доступным =). У каждого приложения своя песочница.И конечно, если приложение будет остановлено системой, то все линки на объекты утратят актуальность и будут очищены сборщиком мусора - следовательно и очиститься нашь static hmap.
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: static HashMap<> - являются ли добавленные данные статич
Когда система грохает приложение все статики затираются, поэтому в них нельзя хранить информацию, которую нельзя восстановить из другого места.Mikhail_dev писал(а):Может кто мне пояснит русским языком почему статики это плохо? Я вот ни одного аргумента не услышал
Я не говорил, что это имитация сворачивания, это имитация долгого нахождения в свернутом состоянии. Уж поверь мне, я на это много времени потратил. Судя по тому, что говорят в интернетах, это именно то, что делает система для освобождения памяти от давно свернутых приложений.Mikhail_dev писал(а):Чего?! А с этого момента поподробнее. С чего вдруг system.exit(0) - это имитация сворчачивания? Денис, ты ли это? о_О Это закрытие процесса, даже не процесса, а приложения, и он сработал так, как надо в этом коде.После нажатия сразу сверните приложение, через 5 секунд разверните. Активити должно восстановиться до состояния перед сворачиванием. В вашем же случае все данные будут затерты.
System.exit(0) - Имитация ситуации когда приложение находится долго в свернутом состоянии.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: static HashMap<> - являются ли добавленные данные статич
Я не понял из твоих слов каким боком тут статик ссылки. разговор о System.exit(0) не входит сюда никаким образом и тот код очень странный.
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: static HashMap<> - являются ли добавленные данные статич
System.exit(0) убивает все статик ссылки.Mikhail_dev писал(а):Я не понял из твоих слов каким боком тут статик ссылки. разговор о System.exit(0) не входит сюда никаким образом и тот код очень странный.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: static HashMap<> - являются ли добавленные данные статич
Он убивает приложение, а не статик ссылки. Покажи мне ссылки где написано что убивает статик ссылки.
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: static HashMap<> - являются ли добавленные данные статич
System.exit(0) убивает приложение
+
Убитое приложение теряет все статик ссылки
=
System.exit(0) убивает все статик ссылки.
+
Убитое приложение теряет все статик ссылки
=
System.exit(0) убивает все статик ссылки.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: static HashMap<> - являются ли добавленные данные статич
Великолепная логика
"Не используйте статик ссылки. Вы можете проверить почему, запустив команду System.exit(0), которая убьёт приложение, а с ним и все статик ссылки. То, что оно убьёт вообще все приложение со всеми его статическимиp и динамическими объектами, а не просто статические, это неважно. Главное помните - не используйте статик ссылки".
В итоге вопрос: почему нельзя использовать статик ссылки?
"Не используйте статик ссылки. Вы можете проверить почему, запустив команду System.exit(0), которая убьёт приложение, а с ним и все статик ссылки. То, что оно убьёт вообще все приложение со всеми его статическимиp и динамическими объектами, а не просто статические, это неважно. Главное помните - не используйте статик ссылки".
В итоге вопрос: почему нельзя использовать статик ссылки?
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: static HashMap<> - являются ли добавленные данные статич
Используя эту логику я могу написать приложение которое развернется и продолжит свою работу как ни в чем не бывало даже если его убить этой командой. А система это может сделать. Ей наплевать, что у тебя там статика или динамика.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.