Страница 1 из 1

Несколько Fragment и CursorLoader

Добавлено: 10 фев 2014, 17:13
MikeIV
В активити есть два фрагмента с ListView в каждом. ListView получают данные из разных таблиц базы через CursorLoader.

[syntax=java]
public class MyFragment1 extends Fragment implements OnItemSelectedListener, OnItemClickListener, LoaderCallbacks<Cursor> {

private static final String DEBUG_TAG = "myLogs";

private DataBase db;
private ListView myList;
private SimpleCursorAdapter myAdapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_1, container, false);

myList = (ListView) v.findViewById(R.id.listView_points);


String[] from = { DataBase.COLUMN_DATETIME};
int[] to = { R.id.textView_date};
myAdapter = new SimpleCursorAdapter(getActivity(), R.layout.point_list_item, null, from, to, 0);

myList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
myList.setAdapter(myAdapter);
myList.setOnItemClickListener(this);

getActivity().getSupportLoaderManager().initLoader(0, null, this);

return v;
}

@Override
public void onAttach(Activity activity) {
if (!(activity instanceof MainActivity)) {
throw new IllegalStateException(
"Activity must implement MainActivity.");
}
db = ((MainActivity) activity).getDataBase();
super.onAttach(activity);
}


@Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {


}
static class MyCursorLoader extends CursorLoader {

DataBase db;

public MyCursorLoader(Context context, DataBase db) {
super(context);
this.db = db;
}

@Override
public Cursor loadInBackground() {
Cursor cursor = db.getAllPointData();
return cursor;
}

}

@Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub

}

@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new MyCursorLoader(getActivity(), db);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cur) {
myAdapter.changeCursor(cur);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
myAdapter.changeCursor(null);
}

}[/syntax]

В первом фрагменте вызывается:

Код: Выделить всё

getActivity().getSupportLoaderManager().initLoader(0, null, this);
Во втором:

Код: Выделить всё

getActivity().getSupportLoaderManager().initLoader(1, null, this);
Такой вариант работает, но создаётся 2 потока AsyncTask. Чувствую что что-то у меня не так сделано.
Что не так? Как сделать чтобы не плодились потоки? Может эту задачу вообще лучше по-другому решать?

Re: Несколько Fragment и CursorLoader

Добавлено: 10 фев 2014, 17:33
anber
два фрагмента - два потока, вроде все логично, что не так?

Re: Несколько Fragment и CursorLoader

Добавлено: 10 фев 2014, 17:56
MikeIV
Смущает, что один поток просто висит без дела, пока фрагмент скрыт. Или я что-то перемудрил?

Re: Несколько Fragment и CursorLoader

Добавлено: 10 фев 2014, 19:33
anber
В смысле висит без дела? Он выполнится и завершится, если он стартовал.

Re: Несколько Fragment и CursorLoader

Добавлено: 10 фев 2014, 21:51
MikeIV
anber, наверно я не совсем ясно объяснил суть проблемы.

Изображение

Поток AsyncTask это CursorLoader. Получается, что CursorLoader остался от убранного фрагмента. От убранных объектов не должно ничего оставаться (backstack пока нету). Что-то я не так делаю. Tакое впечатление, что неправильно использую CursorLoader...

Re: Несколько Fragment и CursorLoader

Добавлено: 10 фев 2014, 22:16
Mikhail_dev
У меня есть стойкое предположение, что прошлую активность и её фрагменты, может держать ссылка db, которая инициализируется в onCreate. Чисто по логике, мы сделали связь с активностью, а в onDetach не обнулили ссылку.
Как проверить:
1. Занулять ссылку в onDetach, а дальше переворачивать устройство, при этом наблюдать, увеличивается ли кол-во потоков, а также наблюдать растет ли heap. Если растет, значит на лицо утечка.
2. Несколько раз попереворачивать экран, дальше снять дамп памяти и посмотреть его через MAT на предмет одинаковых экземпляров к примеру одной и той же активности или фрагмента.

Re: Несколько Fragment и CursorLoader

Добавлено: 10 фев 2014, 22:51
anber
В общем-то да db = ((MainActivity) activity).getDataBase(); как бы это сказать, потенциально опасная конструкция, постарайся от нее избавиться. Вот я примерчик накидал, можешь глянуть там https://github.com/akadatsky/LoaderExample конкретно этот класс:
https://github.com/akadatsky/LoaderExam ... e.java#L43

Re: Несколько Fragment и CursorLoader

Добавлено: 11 фев 2014, 12:58
MikeIV

Код: Выделить всё

private static UserDatabase singleton;
public synchronized static UserDatabase get(Context context) {
    if (singleton == null) {
      singleton = new UserDatabase(context.getApplicationContext());
    }
    return singleton;
  }
Сделал в классе такую конструкцию, но это не помогло ((
m090050 писал(а):У меня есть стойкое предположение, что прошлую активность и её фрагменты, может держать ссылка db, которая инициализируется в onCreate. Чисто по логике, мы сделали связь с активностью, а в onDetach не обнулили ссылку.
Активити один с несколькими фрагментами.
m090050 писал(а): Как проверить:
1. Занулять ссылку в onDetach, а дальше переворачивать устройство, при этом наблюдать, увеличивается ли кол-во потоков, а также наблюдать растет ли heap. Если растет, значит на лицо утечка.
Тоже не помогло ((
m090050 писал(а): 2. Несколько раз попереворачивать экран, дальше снять дамп памяти и посмотреть его через MAT на предмет одинаковых экземпляров к примеру одной и той же активности или фрагмента.
Если я правильно разобрался то утечки памяти нет.
android2191185809399292990.7z