Урок 136. CursorLoader
Re: Урок 136. CursorLoader
KamiSempai, спасибо!
Re: Урок 136. CursorLoader
Неа, это фундаментальная основа pull to refresh патерна. Просто я не вижу более наглядного способа объяснить принцип загрузки в память только видимой части контента, чем постраничный вывод. Ну и как бы в абстрактном восприятии видимой части listview с ее содержимым, в качестве страницы -ничего плохого я не вижу. А отличия в том, чтобы грузить следующую страницу( группу элементов ) или один элемент формирующий listview - не существенны в данном случае... хотя на последнюю инстанцию я не претендую и рад буду если меня кто - то чему -то новому научитKamiSempai писал(а):Это, что, тролинг???altwin писал(а):существует такое понятие, как pagination, подразумевающее ограничение выдачи с последующей возможностью пролистывания( помоему для определения -это коряво звучит) и применимо оно к любой коллекции. Вам нужно идти в сторону custom listview.
Ярослав, нужно делать кастомный адаптер и сжимать изображения перед отображением в списке.
Это должно помочь: viewtopic.php?f=3&t=2961&p=32859#p32596

- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: Урок 136. CursorLoader
Тут не в этом проблема. Я более чем уверен, что он загружает только видимую часть контента. Просто, если, даже в маленький ImageView загрузить фотографию в HD качестве - это будет потреблять большое количество ресурсов и постраничная прокрутка тут не поможет.altwin писал(а):Неа, это фундаментальная основа pull to refresh патерна. Просто я не вижу более наглядного способа объяснить принцип загрузки в память только видимой части контента, чем постраничный вывод. Ну и как бы в абстрактном восприятии видимой части listview с ее содержимым, в качестве страницы -ничего плохого я не вижу. А отличия в том, чтобы грузить следующую страницу( группу элементов ) или один элемент формирующий listview - не существенны в данном случае... хотя на последнюю инстанцию я не претендую и рад буду если меня кто - то чему -то новому научитKamiSempai писал(а):Это, что, тролинг???altwin писал(а):существует такое понятие, как pagination, подразумевающее ограничение выдачи с последующей возможностью пролистывания( помоему для определения -это коряво звучит) и применимо оно к любой коллекции. Вам нужно идти в сторону custom listview.
Перед выводом картинки в список ее обязательно нужно ужимать до необходимых размеров. Многие это не знают. В итоге получаем тормознутые приложения даже в топах Google Play. Я такие видел. Видимо, создатель поленился сделать миниатюры для изображений.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
Re: Урок 136. CursorLoader
KamiSempai, расскажите про создание миниатюр для изображений.
Re: Урок 136. CursorLoader
Посмотрите лучше на работаюие примеры: функция createScaledBitmap делает то, что вам нужно. Либо вот популярная библиотека позволяющая грузить image из url и выводить в том чисте в listView, там вы найдете много интересного внутри даже с кешированием картинок https://github.com/nostra13/Android-Uni ... Utils.javaЯрослав писал(а):KamiSempai, расскажите про создание миниатюр для изображений.

Re: Урок 136. CursorLoader
Всем добрый день ! Спасибо за инфу, узнал много нового )) Но остались и вопросы...
Я, так понял, что лоадер применяется в основном для получения информации из БД (например) и последующего ее отображения в элементах UI. А что делать с такими операциями как insert, update, delete, их можно прямо UI-потоке делать ? Так же операция чтения из БД, обработка и обновления БД, без вывода на экран ? Или их надо, например, в АсинкТаск выносить ?
И второй вопрос - как все таки правильно работать с БД из нескольких активити + из сервиса ? КонтентПровайдер или без него можно обойтись ?
Спасибо....
Я, так понял, что лоадер применяется в основном для получения информации из БД (например) и последующего ее отображения в элементах UI. А что делать с такими операциями как insert, update, delete, их можно прямо UI-потоке делать ? Так же операция чтения из БД, обработка и обновления БД, без вывода на экран ? Или их надо, например, в АсинкТаск выносить ?
И второй вопрос - как все таки правильно работать с БД из нескольких активити + из сервиса ? КонтентПровайдер или без него можно обойтись ?
Спасибо....
Re: Урок 136. CursorLoader
люди добрые! помогите начинающему программисту. Я попытался изменить код урока так чтобы при нажатии на кнопку "Добавить запись" добавлялась не одна строка и картинка, а две строки и картинка. Мучаюсь второй день - не пойму что я делаю не так. Выручайте
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher">
</ImageView>
<TextView
android:id="@+id/tvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:text=""
android:textSize="18sp">
</TextView>
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" >
</TextView>
</LinearLayout>
DB.java
package ru.android.p1361_cursorloader;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class DB {
private static final String DB_NAME = "mydb";
private static final int DB_VERSION = 1;
private static final String DB_TABLE = "mytab";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_IMG = "img";
public static final String COLUMN_TXT = "txt";
public static final String COLUMN_NAME = "name";
private static final String DB_CREATE =
"create table " + DB_TABLE + "(" +
COLUMN_ID + " integer primary key autoincrement, " +
COLUMN_IMG + " integer, " +
COLUMN_TXT + " text" +
COLUMN_NAME + " name" +
");";
private final Context mCtx;
private DBHelper mDBHelper;
private SQLiteDatabase mDB;
public DB(Context ctx) {
mCtx = ctx;
}
// открыть подключение
public void open() {
mDBHelper = new DBHelper(mCtx, DB_NAME, null, DB_VERSION);
mDB = mDBHelper.getWritableDatabase();
}
// закрыть подключение
public void close() {
if (mDBHelper!=null) mDBHelper.close();
}
// получить все данные из таблицы DB_TABLE
public Cursor getAllData() {
return mDB.query(DB_TABLE, null, null, null, null, null, null);
}
// добавить запись в DB_TABLE
public void addRec(String txt, String name, int img) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, name);
cv.put(COLUMN_TXT, txt);
cv.put(COLUMN_IMG, img);
mDB.insert(DB_TABLE, null, cv);
}
// удалить запись из DB_TABLE
public void delRec(long id) {
mDB.delete(DB_TABLE, COLUMN_ID + " = " + id, null);
}
// класс по созданию и управлению БД
private class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
// создаем и заполняем БД
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_CREATE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, "nametext ");
cv.put(COLUMN_TXT, "sometext ");
cv.put(COLUMN_IMG, R.drawable.ic_launcher);
db.insert(DB_TABLE, null, cv);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}
MainActivity.java
package ru.android.p1361_cursorloader;
import java.util.concurrent.TimeUnit;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
private static final int CM_DELETE_ID = 1;
ListView lvData;
DB db;
SimpleCursorAdapter scAdapter;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// открываем подключение к БД
db = new DB(this);
db.open();
// формируем столбцы сопоставления
String[] from = new String[] { DB.COLUMN_IMG, DB.COLUMN_TXT, DB.COLUMN_NAME };
int[] to = new int[] { R.id.ivImg, R.id.tvText, R.id.tvName };
// создааем адаптер и настраиваем список
scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to, 0);
lvData = (ListView) findViewById(R.id.lvData);
lvData.setAdapter(scAdapter);
// добавляем контекстное меню к списку
registerForContextMenu(lvData);
// создаем лоадер для чтения данных
getSupportLoaderManager().initLoader(0, null, this);
}
// обработка нажатия кнопки
public void onButtonClick(View view) {
// добавляем запись
db.addRec("sometext " + (scAdapter.getCount() + 1), "name " + (scAdapter.getCount() + 1), R.drawable.ic_launcher);
// получаем новый курсор с данными
getSupportLoaderManager().getLoader(0).forceLoad();
}
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, CM_DELETE_ID, 0, R.string.delete_record);
}
public boolean onContextItemSelected(MenuItem item) {
if (item.getItemId() == CM_DELETE_ID) {
// получаем из пункта контекстного меню данные по пункту списка
AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) item
.getMenuInfo();
// извлекаем id записи и удаляем соответствующую запись в БД
db.delRec(acmi.id);
// получаем новый курсор с данными
getSupportLoaderManager().getLoader(0).forceLoad();
return true;
}
return super.onContextItemSelected(item);
}
protected void onDestroy() {
super.onDestroy();
// закрываем подключение при выходе
db.close();
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bndl) {
return new MyCursorLoader(this, db);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
scAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
static class MyCursorLoader extends CursorLoader {
DB db;
public MyCursorLoader(Context context, DB db) {
super(context);
this.db = db;
}
@Override
public Cursor loadInBackground() {
Cursor cursor = db.getAllData();
try {
TimeUnit.SECONDS.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
return cursor;
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher">
</ImageView>
<TextView
android:id="@+id/tvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:text=""
android:textSize="18sp">
</TextView>
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" >
</TextView>
</LinearLayout>
DB.java
package ru.android.p1361_cursorloader;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class DB {
private static final String DB_NAME = "mydb";
private static final int DB_VERSION = 1;
private static final String DB_TABLE = "mytab";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_IMG = "img";
public static final String COLUMN_TXT = "txt";
public static final String COLUMN_NAME = "name";
private static final String DB_CREATE =
"create table " + DB_TABLE + "(" +
COLUMN_ID + " integer primary key autoincrement, " +
COLUMN_IMG + " integer, " +
COLUMN_TXT + " text" +
COLUMN_NAME + " name" +
");";
private final Context mCtx;
private DBHelper mDBHelper;
private SQLiteDatabase mDB;
public DB(Context ctx) {
mCtx = ctx;
}
// открыть подключение
public void open() {
mDBHelper = new DBHelper(mCtx, DB_NAME, null, DB_VERSION);
mDB = mDBHelper.getWritableDatabase();
}
// закрыть подключение
public void close() {
if (mDBHelper!=null) mDBHelper.close();
}
// получить все данные из таблицы DB_TABLE
public Cursor getAllData() {
return mDB.query(DB_TABLE, null, null, null, null, null, null);
}
// добавить запись в DB_TABLE
public void addRec(String txt, String name, int img) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, name);
cv.put(COLUMN_TXT, txt);
cv.put(COLUMN_IMG, img);
mDB.insert(DB_TABLE, null, cv);
}
// удалить запись из DB_TABLE
public void delRec(long id) {
mDB.delete(DB_TABLE, COLUMN_ID + " = " + id, null);
}
// класс по созданию и управлению БД
private class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
// создаем и заполняем БД
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_CREATE);
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, "nametext ");
cv.put(COLUMN_TXT, "sometext ");
cv.put(COLUMN_IMG, R.drawable.ic_launcher);
db.insert(DB_TABLE, null, cv);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}
MainActivity.java
package ru.android.p1361_cursorloader;
import java.util.concurrent.TimeUnit;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
private static final int CM_DELETE_ID = 1;
ListView lvData;
DB db;
SimpleCursorAdapter scAdapter;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// открываем подключение к БД
db = new DB(this);
db.open();
// формируем столбцы сопоставления
String[] from = new String[] { DB.COLUMN_IMG, DB.COLUMN_TXT, DB.COLUMN_NAME };
int[] to = new int[] { R.id.ivImg, R.id.tvText, R.id.tvName };
// создааем адаптер и настраиваем список
scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to, 0);
lvData = (ListView) findViewById(R.id.lvData);
lvData.setAdapter(scAdapter);
// добавляем контекстное меню к списку
registerForContextMenu(lvData);
// создаем лоадер для чтения данных
getSupportLoaderManager().initLoader(0, null, this);
}
// обработка нажатия кнопки
public void onButtonClick(View view) {
// добавляем запись
db.addRec("sometext " + (scAdapter.getCount() + 1), "name " + (scAdapter.getCount() + 1), R.drawable.ic_launcher);
// получаем новый курсор с данными
getSupportLoaderManager().getLoader(0).forceLoad();
}
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, CM_DELETE_ID, 0, R.string.delete_record);
}
public boolean onContextItemSelected(MenuItem item) {
if (item.getItemId() == CM_DELETE_ID) {
// получаем из пункта контекстного меню данные по пункту списка
AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) item
.getMenuInfo();
// извлекаем id записи и удаляем соответствующую запись в БД
db.delRec(acmi.id);
// получаем новый курсор с данными
getSupportLoaderManager().getLoader(0).forceLoad();
return true;
}
return super.onContextItemSelected(item);
}
protected void onDestroy() {
super.onDestroy();
// закрываем подключение при выходе
db.close();
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bndl) {
return new MyCursorLoader(this, db);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
scAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
static class MyCursorLoader extends CursorLoader {
DB db;
public MyCursorLoader(Context context, DB db) {
super(context);
this.db = db;
}
@Override
public Cursor loadInBackground() {
Cursor cursor = db.getAllData();
try {
TimeUnit.SECONDS.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
return cursor;
}
}
}
Re: Урок 136. CursorLoader
Приветствую.
Изучаю урок 136.
Использую Android Studio.
Возникла проблема на этой строке
SimpleCursorAdapter зачеркивается и пишет, что Deprecated.
Возможно проблема в блоке import`а
вот кусок кода:
LoaderManager, CursorLoader, Loader и SimpleCursorAdapter выделены красным шрифтом
подвожу курсор и вижу Cannot resolve sumbol 'LoaderManager'
что-то не то с версией SDK?
Что и где подсмотреть и исправить?
Спасибо.
Изучаю урок 136.
Использую Android Studio.
Возникла проблема на этой строке
Код: Выделить всё
scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to);Возможно проблема в блоке import`а
вот кусок кода:
Код: Выделить всё
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;подвожу курсор и вижу Cannot resolve sumbol 'LoaderManager'
что-то не то с версией SDK?
Что и где подсмотреть и исправить?
Спасибо.
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: Урок 136. CursorLoader
Deprecated только этот конструктор класса. Нужно добавить последним параметром flag, тогда зачеркивать не будет. Можно указать 0.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
Re: Урок 136. CursorLoader
Спасибо!
Re: Урок 136. CursorLoader
Теперь проблема с getSupportLoaderManager
на строке
getSupportLoaderManager().initLoader(0, null, this);
тоже пишет, что cannot resolve method
на строке
getSupportLoaderManager().initLoader(0, null, this);
тоже пишет, что cannot resolve method
Re: Урок 136. CursorLoader
если добавить
import android.support.v4.app.FragmentActivity;
то support выделяет красным
import android.support.v4.app.FragmentActivity;
то support выделяет красным
Re: Урок 136. CursorLoader
гугль привёл сюда
https://stackoverflow.com/questions/216 ... 8#26049978
добавил в Andriod Studio так же
http://f5.s.qip.ru/adNBVy17.png
https://stackoverflow.com/questions/216 ... 8#26049978
добавил в Andriod Studio так же
http://f5.s.qip.ru/adNBVy17.png
Re: Урок 136. CursorLoader
проверяй, так же, чтоб у тебя импорты не смешивались - либо саппорт либо обычная во всех классах.
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: Урок 136. CursorLoader
да, это я уже понял, да и студия в таком случае даёт подсказку
Re: Урок 136. CursorLoader
Приветствую.
Нельзя более подробно описать этот кусок кода
Список полей таблицы и список визуальных элементов должны строго совпадать и по типам и по количеству? А если полей много, типы разные? Как контролировать?
Нельзя более подробно описать этот кусок кода
Код: Выделить всё
// формируем столбцы сопоставления
String[] from = new String[] { DB.COLUMN_IMG, DB.COLUMN_TXT };
int[] to = new int[] { R.id.ivImg, R.id.tvText };
// создааем адаптер и настраиваем список
scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to, 0);Re: Урок 136. CursorLoader
Этот урок у меня не получился. Я использую Андроид 4.2. Программа по умолчанию ставит следующие библиотеки
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.ListView;
и на метод getSupportLoaderManager() выдает ошибку
предлагает поменять на getLoaderManager() или создать данный метод.
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.ListView;
и на метод getSupportLoaderManager() выдает ошибку
предлагает поменять на getLoaderManager() или создать данный метод.
Re: Урок 136. CursorLoader
К предыдущему:
Я сделал урок, как он есть, все получилось. НО!
Разница моего предыдущего варианта лишь в том, что я создал задачу не в главном активити, а во втором. То есть, первая активити запускает второе, и вот там уже должен работать список.
Проблема та же:
на метод getSupportLoaderManager() выдает ошибку
Хотя весь текст приложения - тот же.
Я сделал урок, как он есть, все получилось. НО!
Разница моего предыдущего варианта лишь в том, что я создал задачу не в главном активити, а во втором. То есть, первая активити запускает второе, и вот там уже должен работать список.
Проблема та же:
на метод getSupportLoaderManager() выдает ошибку
Хотя весь текст приложения - тот же.
Re: Урок 136. CursorLoader
проверь импорты - у тебя ВЕЗДЕ должна использовать саппорт-либа, во всех активити, классах и прочих.
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: Урок 136. CursorLoader
вероятно наследственность плохая: попробуй вместо Activity, скажем, FragmentActivity